├── .changeset ├── clean-ways-push.md ├── config.json ├── fine-frogs-bake.md ├── full-ways-help.md ├── funny-years-yawn.md ├── hot-grapes-lie.md ├── lazy-poets-cheer.md ├── long-hornets-mate.md ├── lucky-donuts-scream.md ├── nice-rings-wish.md ├── pink-dolls-shop.md ├── popular-geese-tan.md ├── proud-tables-sip.md ├── quiet-kiwis-feel.md ├── rare-shirts-unite.md ├── ripe-bears-hide.md ├── rotten-apes-lie.md ├── social-walls-obey.md ├── sour-pens-shake.md ├── strong-points-change.md ├── tame-bears-mix.md └── wet-dodos-reply.md ├── .codecov.yml ├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md ├── actions │ ├── gas-compare │ │ └── action.yml │ ├── setup │ │ └── action.yml │ └── storage-layout │ │ └── action.yml └── workflows │ ├── actionlint.yml │ ├── changeset.yml │ ├── checks.yml │ ├── docs.yml │ ├── formal-verification.yml │ ├── release-cycle.yml │ └── upgradeable.yml ├── .gitignore ├── .gitmodules ├── .husky └── pre-commit ├── .mocharc.js ├── .prettierrc ├── .solcover.js ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── FUNDING.json ├── GUIDELINES.md ├── LICENSE ├── README.md ├── RELEASING.md ├── SECURITY.md ├── audits ├── 2017-03.md ├── 2018-10.pdf ├── 2022-10-Checkpoints.pdf ├── 2022-10-ERC4626.pdf ├── 2023-05-v4.9.pdf ├── 2023-10-v5.0.pdf ├── 2024-10-v5.1.pdf ├── 2024-12-v5.2.pdf ├── 2025-04-v5.3.pdf └── README.md ├── certora ├── .gitignore ├── Makefile ├── README.md ├── diff │ └── access_manager_AccessManager.sol.patch ├── harnesses │ ├── AccessControlDefaultAdminRulesHarness.sol │ ├── AccessControlHarness.sol │ ├── AccessManagedHarness.sol │ ├── AccessManagerHarness.sol │ ├── DoubleEndedQueueHarness.sol │ ├── ERC20FlashMintHarness.sol │ ├── ERC20PermitHarness.sol │ ├── ERC20WrapperHarness.sol │ ├── ERC3156FlashBorrowerHarness.sol │ ├── ERC721Harness.sol │ ├── ERC721ReceiverHarness.sol │ ├── EnumerableMapHarness.sol │ ├── EnumerableSetHarness.sol │ ├── InitializableHarness.sol │ ├── NoncesHarness.sol │ ├── Ownable2StepHarness.sol │ ├── OwnableHarness.sol │ ├── PausableHarness.sol │ └── TimelockControllerHarness.sol ├── reports │ ├── 2021-10.pdf │ ├── 2022-03.pdf │ └── 2022-05.pdf ├── run.js ├── specs.json └── specs │ ├── AccessControl.spec │ ├── AccessControlDefaultAdminRules.spec │ ├── AccessManaged.spec │ ├── AccessManager.spec │ ├── DoubleEndedQueue.spec │ ├── ERC20.spec │ ├── ERC20FlashMint.spec │ ├── ERC20Wrapper.spec │ ├── ERC721.spec │ ├── EnumerableMap.spec │ ├── EnumerableSet.spec │ ├── Initializable.spec │ ├── Nonces.spec │ ├── Ownable.spec │ ├── Ownable2Step.spec │ ├── Pausable.spec │ ├── TimelockController.spec │ ├── helpers │ └── helpers.spec │ └── methods │ ├── IAccessControl.spec │ ├── IAccessControlDefaultAdminRules.spec │ ├── IAccessManaged.spec │ ├── IAccessManager.spec │ ├── IERC20.spec │ ├── IERC2612.spec │ ├── IERC3156FlashBorrower.spec │ ├── IERC3156FlashLender.spec │ ├── IERC5313.spec │ ├── IERC721.spec │ ├── IERC721Receiver.spec │ ├── IOwnable.spec │ └── IOwnable2Step.spec ├── contracts ├── access │ ├── AccessControl.sol │ ├── IAccessControl.sol │ ├── Ownable.sol │ ├── Ownable2Step.sol │ ├── README.adoc │ ├── extensions │ │ ├── AccessControlDefaultAdminRules.sol │ │ ├── AccessControlEnumerable.sol │ │ ├── IAccessControlDefaultAdminRules.sol │ │ └── IAccessControlEnumerable.sol │ └── manager │ │ ├── AccessManaged.sol │ │ ├── AccessManager.sol │ │ ├── AuthorityUtils.sol │ │ ├── IAccessManaged.sol │ │ ├── IAccessManager.sol │ │ └── IAuthority.sol ├── account │ ├── Account.sol │ ├── README.adoc │ ├── extensions │ │ ├── ERC7821.sol │ │ ├── draft-AccountERC7579.sol │ │ └── draft-AccountERC7579Hooked.sol │ └── utils │ │ ├── EIP7702Utils.sol │ │ ├── draft-ERC4337Utils.sol │ │ └── draft-ERC7579Utils.sol ├── finance │ ├── README.adoc │ ├── VestingWallet.sol │ └── VestingWalletCliff.sol ├── governance │ ├── Governor.sol │ ├── IGovernor.sol │ ├── README.adoc │ ├── TimelockController.sol │ ├── extensions │ │ ├── GovernorCountingFractional.sol │ │ ├── GovernorCountingOverridable.sol │ │ ├── GovernorCountingSimple.sol │ │ ├── GovernorNoncesKeyed.sol │ │ ├── GovernorPreventLateQuorum.sol │ │ ├── GovernorProposalGuardian.sol │ │ ├── GovernorSequentialProposalId.sol │ │ ├── GovernorSettings.sol │ │ ├── GovernorStorage.sol │ │ ├── GovernorSuperQuorum.sol │ │ ├── GovernorTimelockAccess.sol │ │ ├── GovernorTimelockCompound.sol │ │ ├── GovernorTimelockControl.sol │ │ ├── GovernorVotes.sol │ │ ├── GovernorVotesQuorumFraction.sol │ │ └── GovernorVotesSuperQuorumFraction.sol │ └── utils │ │ ├── IVotes.sol │ │ ├── Votes.sol │ │ └── VotesExtended.sol ├── interfaces │ ├── IERC1155.sol │ ├── IERC1155MetadataURI.sol │ ├── IERC1155Receiver.sol │ ├── IERC1271.sol │ ├── IERC1363.sol │ ├── IERC1363Receiver.sol │ ├── IERC1363Spender.sol │ ├── IERC165.sol │ ├── IERC1820Implementer.sol │ ├── IERC1820Registry.sol │ ├── IERC1967.sol │ ├── IERC20.sol │ ├── IERC20Metadata.sol │ ├── IERC2309.sol │ ├── IERC2612.sol │ ├── IERC2981.sol │ ├── IERC3156.sol │ ├── IERC3156FlashBorrower.sol │ ├── IERC3156FlashLender.sol │ ├── IERC4626.sol │ ├── IERC4906.sol │ ├── IERC5267.sol │ ├── IERC5313.sol │ ├── IERC5805.sol │ ├── IERC6372.sol │ ├── IERC721.sol │ ├── IERC721Enumerable.sol │ ├── IERC721Metadata.sol │ ├── IERC721Receiver.sol │ ├── IERC777.sol │ ├── IERC777Recipient.sol │ ├── IERC777Sender.sol │ ├── IERC7821.sol │ ├── IERC7913.sol │ ├── README.adoc │ ├── draft-IERC1822.sol │ ├── draft-IERC4337.sol │ ├── draft-IERC6093.sol │ ├── draft-IERC6909.sol │ ├── draft-IERC7579.sol │ ├── draft-IERC7674.sol │ └── draft-IERC7802.sol ├── metatx │ ├── ERC2771Context.sol │ ├── ERC2771Forwarder.sol │ └── README.adoc ├── mocks │ ├── AccessManagedTarget.sol │ ├── AccessManagerMock.sol │ ├── ArraysMock.sol │ ├── AuthorityMock.sol │ ├── Base64Dirty.sol │ ├── BatchCaller.sol │ ├── CallReceiverMock.sol │ ├── ConstructorMock.sol │ ├── ContextMock.sol │ ├── DummyImplementation.sol │ ├── EIP712Verifier.sol │ ├── ERC1271WalletMock.sol │ ├── ERC165 │ │ ├── ERC165InterfacesSupported.sol │ │ ├── ERC165MaliciousData.sol │ │ ├── ERC165MissingData.sol │ │ ├── ERC165NotSupported.sol │ │ └── ERC165ReturnBomb.sol │ ├── ERC2771ContextMock.sol │ ├── ERC3156FlashBorrowerMock.sol │ ├── EtherReceiverMock.sol │ ├── InitializableMock.sol │ ├── MerkleProofCustomHashMock.sol │ ├── MerkleTreeMock.sol │ ├── MulticallHelper.sol │ ├── MultipleInheritanceInitializableMocks.sol │ ├── PausableMock.sol │ ├── ReentrancyAttack.sol │ ├── ReentrancyMock.sol │ ├── ReentrancyTransientMock.sol │ ├── RegressionImplementation.sol │ ├── SingleInheritanceInitializableMocks.sol │ ├── Stateless.sol │ ├── StorageSlotMock.sol │ ├── TimelockReentrant.sol │ ├── TransientSlotMock.sol │ ├── UpgradeableBeaconMock.sol │ ├── VotesExtendedMock.sol │ ├── VotesMock.sol │ ├── account │ │ ├── AccountMock.sol │ │ ├── modules │ │ │ └── ERC7579Mock.sol │ │ └── utils │ │ │ └── ERC7579UtilsMock.sol │ ├── compound │ │ └── CompTimelock.sol │ ├── docs │ │ ├── ERC20WithAutoMinerReward.sol │ │ ├── ERC4626Fees.sol │ │ ├── MyNFT.sol │ │ ├── access-control │ │ │ ├── AccessControlERC20MintBase.sol │ │ │ ├── AccessControlERC20MintMissing.sol │ │ │ ├── AccessControlERC20MintOnlyRole.sol │ │ │ ├── AccessControlModified.sol │ │ │ ├── AccessManagedERC20MintBase.sol │ │ │ └── MyContractOwnable.sol │ │ ├── governance │ │ │ ├── MyGovernor.sol │ │ │ ├── MyToken.sol │ │ │ ├── MyTokenTimestampBased.sol │ │ │ └── MyTokenWrapped.sol │ │ ├── token │ │ │ ├── ERC1155 │ │ │ │ ├── GameItems.sol │ │ │ │ └── MyERC115HolderContract.sol │ │ │ ├── ERC20 │ │ │ │ └── GLDToken.sol │ │ │ ├── ERC6909 │ │ │ │ └── ERC6909GameItems.sol │ │ │ └── ERC721 │ │ │ │ └── GameItem.sol │ │ └── utilities │ │ │ ├── Base64NFT.sol │ │ │ └── Multicall.sol │ ├── governance │ │ ├── GovernorCountingOverridableMock.sol │ │ ├── GovernorFractionalMock.sol │ │ ├── GovernorMock.sol │ │ ├── GovernorNoncesKeyedMock.sol │ │ ├── GovernorPreventLateQuorumMock.sol │ │ ├── GovernorProposalGuardianMock.sol │ │ ├── GovernorSequentialProposalIdMock.sol │ │ ├── GovernorStorageMock.sol │ │ ├── GovernorSuperQuorumMock.sol │ │ ├── GovernorTimelockAccessMock.sol │ │ ├── GovernorTimelockCompoundMock.sol │ │ ├── GovernorTimelockControlMock.sol │ │ ├── GovernorVoteMock.sol │ │ ├── GovernorVotesSuperQuorumFractionMock.sol │ │ └── GovernorWithParamsMock.sol │ ├── proxy │ │ ├── BadBeacon.sol │ │ ├── ClashingImplementation.sol │ │ └── UUPSUpgradeableMock.sol │ ├── token │ │ ├── ERC1155ReceiverMock.sol │ │ ├── ERC1363ForceApproveMock.sol │ │ ├── ERC1363NoReturnMock.sol │ │ ├── ERC1363ReceiverMock.sol │ │ ├── ERC1363ReturnFalseMock.sol │ │ ├── ERC1363SpenderMock.sol │ │ ├── ERC20ApprovalMock.sol │ │ ├── ERC20BridgeableMock.sol │ │ ├── ERC20DecimalsMock.sol │ │ ├── ERC20ExcessDecimalsMock.sol │ │ ├── ERC20FlashMintMock.sol │ │ ├── ERC20ForceApproveMock.sol │ │ ├── ERC20GetterHelper.sol │ │ ├── ERC20Mock.sol │ │ ├── ERC20MulticallMock.sol │ │ ├── ERC20NoReturnMock.sol │ │ ├── ERC20Reentrant.sol │ │ ├── ERC20ReturnFalseMock.sol │ │ ├── ERC20VotesAdditionalCheckpointsMock.sol │ │ ├── ERC20VotesLegacyMock.sol │ │ ├── ERC20VotesTimestampMock.sol │ │ ├── ERC4626LimitsMock.sol │ │ ├── ERC4626Mock.sol │ │ ├── ERC4626OffsetMock.sol │ │ ├── ERC4646FeesMock.sol │ │ ├── ERC721ConsecutiveEnumerableMock.sol │ │ ├── ERC721ConsecutiveMock.sol │ │ ├── ERC721ReceiverMock.sol │ │ └── ERC721URIStorageMock.sol │ └── utils │ │ └── cryptography │ │ └── ERC7739Mock.sol ├── package.json ├── proxy │ ├── Clones.sol │ ├── ERC1967 │ │ ├── ERC1967Proxy.sol │ │ └── ERC1967Utils.sol │ ├── Proxy.sol │ ├── README.adoc │ ├── beacon │ │ ├── BeaconProxy.sol │ │ ├── IBeacon.sol │ │ └── UpgradeableBeacon.sol │ ├── transparent │ │ ├── ProxyAdmin.sol │ │ └── TransparentUpgradeableProxy.sol │ └── utils │ │ ├── Initializable.sol │ │ └── UUPSUpgradeable.sol ├── token │ ├── ERC1155 │ │ ├── ERC1155.sol │ │ ├── IERC1155.sol │ │ ├── IERC1155Receiver.sol │ │ ├── README.adoc │ │ ├── extensions │ │ │ ├── ERC1155Burnable.sol │ │ │ ├── ERC1155Pausable.sol │ │ │ ├── ERC1155Supply.sol │ │ │ ├── ERC1155URIStorage.sol │ │ │ └── IERC1155MetadataURI.sol │ │ └── utils │ │ │ ├── ERC1155Holder.sol │ │ │ └── ERC1155Utils.sol │ ├── ERC20 │ │ ├── ERC20.sol │ │ ├── IERC20.sol │ │ ├── README.adoc │ │ ├── extensions │ │ │ ├── ERC1363.sol │ │ │ ├── ERC20Burnable.sol │ │ │ ├── ERC20Capped.sol │ │ │ ├── ERC20FlashMint.sol │ │ │ ├── ERC20Pausable.sol │ │ │ ├── ERC20Permit.sol │ │ │ ├── ERC20Votes.sol │ │ │ ├── ERC20Wrapper.sol │ │ │ ├── ERC4626.sol │ │ │ ├── IERC20Metadata.sol │ │ │ ├── IERC20Permit.sol │ │ │ ├── draft-ERC20Bridgeable.sol │ │ │ └── draft-ERC20TemporaryApproval.sol │ │ └── utils │ │ │ ├── ERC1363Utils.sol │ │ │ └── SafeERC20.sol │ ├── ERC6909 │ │ ├── README.adoc │ │ ├── draft-ERC6909.sol │ │ └── extensions │ │ │ ├── draft-ERC6909ContentURI.sol │ │ │ ├── draft-ERC6909Metadata.sol │ │ │ └── draft-ERC6909TokenSupply.sol │ ├── ERC721 │ │ ├── ERC721.sol │ │ ├── IERC721.sol │ │ ├── IERC721Receiver.sol │ │ ├── README.adoc │ │ ├── extensions │ │ │ ├── ERC721Burnable.sol │ │ │ ├── ERC721Consecutive.sol │ │ │ ├── ERC721Enumerable.sol │ │ │ ├── ERC721Pausable.sol │ │ │ ├── ERC721Royalty.sol │ │ │ ├── ERC721URIStorage.sol │ │ │ ├── ERC721Votes.sol │ │ │ ├── ERC721Wrapper.sol │ │ │ ├── IERC721Enumerable.sol │ │ │ └── IERC721Metadata.sol │ │ └── utils │ │ │ ├── ERC721Holder.sol │ │ │ └── ERC721Utils.sol │ └── common │ │ ├── ERC2981.sol │ │ └── README.adoc ├── utils │ ├── Address.sol │ ├── Arrays.sol │ ├── Base64.sol │ ├── Blockhash.sol │ ├── Bytes.sol │ ├── CAIP10.sol │ ├── CAIP2.sol │ ├── Calldata.sol │ ├── Comparators.sol │ ├── Context.sol │ ├── Create2.sol │ ├── Errors.sol │ ├── Multicall.sol │ ├── Nonces.sol │ ├── NoncesKeyed.sol │ ├── Packing.sol │ ├── Panic.sol │ ├── Pausable.sol │ ├── README.adoc │ ├── ReentrancyGuard.sol │ ├── ReentrancyGuardTransient.sol │ ├── ShortStrings.sol │ ├── SlotDerivation.sol │ ├── StorageSlot.sol │ ├── Strings.sol │ ├── TransientSlot.sol │ ├── cryptography │ │ ├── ECDSA.sol │ │ ├── EIP712.sol │ │ ├── Hashes.sol │ │ ├── MerkleProof.sol │ │ ├── MessageHashUtils.sol │ │ ├── P256.sol │ │ ├── README.adoc │ │ ├── RSA.sol │ │ ├── SignatureChecker.sol │ │ ├── draft-ERC7739Utils.sol │ │ ├── signers │ │ │ ├── AbstractSigner.sol │ │ │ ├── MultiSignerERC7913.sol │ │ │ ├── SignerECDSA.sol │ │ │ ├── SignerERC7702.sol │ │ │ ├── SignerERC7913.sol │ │ │ ├── SignerP256.sol │ │ │ ├── SignerRSA.sol │ │ │ └── draft-ERC7739.sol │ │ └── verifiers │ │ │ ├── ERC7913P256Verifier.sol │ │ │ └── ERC7913RSAVerifier.sol │ ├── introspection │ │ ├── ERC165.sol │ │ ├── ERC165Checker.sol │ │ └── IERC165.sol │ ├── math │ │ ├── Math.sol │ │ ├── SafeCast.sol │ │ └── SignedMath.sol │ ├── structs │ │ ├── BitMaps.sol │ │ ├── Checkpoints.sol │ │ ├── CircularBuffer.sol │ │ ├── DoubleEndedQueue.sol │ │ ├── EnumerableMap.sol │ │ ├── EnumerableSet.sol │ │ ├── Heap.sol │ │ └── MerkleTree.sol │ └── types │ │ └── Time.sol └── vendor │ └── compound │ ├── ICompoundTimelock.sol │ └── LICENSE ├── docs ├── README.md ├── antora.yml ├── config.js ├── modules │ └── ROOT │ │ ├── images │ │ ├── access-control-multiple.svg │ │ ├── access-manager-functions.svg │ │ ├── access-manager.svg │ │ ├── erc4626-attack-3a.png │ │ ├── erc4626-attack-3b.png │ │ ├── erc4626-attack-6.png │ │ ├── erc4626-attack.png │ │ ├── erc4626-deposit.png │ │ ├── erc4626-mint.png │ │ ├── erc4626-rate-linear.png │ │ ├── erc4626-rate-loglog.png │ │ ├── erc4626-rate-loglogext.png │ │ ├── tally-exec.png │ │ └── tally-vote.png │ │ ├── nav.adoc │ │ └── pages │ │ ├── access-control.adoc │ │ ├── backwards-compatibility.adoc │ │ ├── erc1155.adoc │ │ ├── erc20-supply.adoc │ │ ├── erc20.adoc │ │ ├── erc4626.adoc │ │ ├── erc6909.adoc │ │ ├── erc721.adoc │ │ ├── extending-contracts.adoc │ │ ├── faq.adoc │ │ ├── governance.adoc │ │ ├── index.adoc │ │ ├── tokens.adoc │ │ ├── upgradeable.adoc │ │ ├── utilities.adoc │ │ └── wizard.adoc └── templates │ ├── contract.hbs │ ├── helpers.js │ ├── page.hbs │ └── properties.js ├── eslint.config.mjs ├── foundry.toml ├── fv-requirements.txt ├── hardhat.config.js ├── hardhat ├── async-test-sanity.js ├── common-contracts.js ├── env-artifacts.js ├── ignore-unreachable-warnings.js ├── remappings.js ├── skip-foundry-tests.js └── task-test-get-files.js ├── logo.svg ├── netlify.toml ├── package-lock.json ├── package.json ├── remappings.txt ├── renovate.json ├── scripts ├── checks │ ├── compare-layout.js │ ├── compareGasReports.js │ ├── coverage.sh │ ├── extract-layout.js │ ├── generation.sh │ ├── inheritance-ordering.js │ └── pragma-validity.js ├── fetch-common-contracts.js ├── gen-nav.js ├── generate │ ├── format-lines.js │ ├── helpers │ │ └── sanitize.js │ ├── run.js │ └── templates │ │ ├── Arrays.js │ │ ├── Arrays.opts.js │ │ ├── Checkpoints.js │ │ ├── Checkpoints.opts.js │ │ ├── Checkpoints.t.js │ │ ├── Enumerable.opts.js │ │ ├── EnumerableMap.js │ │ ├── EnumerableSet.js │ │ ├── MerkleProof.js │ │ ├── MerkleProof.opts.js │ │ ├── Packing.js │ │ ├── Packing.opts.js │ │ ├── Packing.t.js │ │ ├── SafeCast.js │ │ ├── Slot.opts.js │ │ ├── SlotDerivation.js │ │ ├── SlotDerivation.t.js │ │ ├── StorageSlot.js │ │ ├── StorageSlotMock.js │ │ ├── TransientSlot.js │ │ ├── TransientSlotMock.js │ │ └── conversion.js ├── get-contracts-metadata.js ├── git-user-config.sh ├── helpers.js ├── prepack.sh ├── prepare-docs.sh ├── release │ ├── format-changelog.js │ ├── synchronize-versions.js │ ├── update-comment.js │ ├── version.sh │ └── workflow │ │ ├── exit-prerelease.sh │ │ ├── github-release.js │ │ ├── integrity-check.sh │ │ ├── pack.sh │ │ ├── publish.sh │ │ ├── rerun.js │ │ ├── set-changesets-pr-title.js │ │ ├── start.sh │ │ └── state.js ├── remove-ignored-artifacts.js ├── set-max-old-space-size.sh ├── solc-versions.js ├── solhint-custom │ ├── index.js │ └── package.json ├── update-docs-branch.js └── upgradeable │ ├── README.md │ ├── patch-apply.sh │ ├── patch-save.sh │ ├── transpile-onto.sh │ ├── transpile.sh │ └── upgradeable.patch ├── slither.config.json ├── solhint.config.js └── test ├── TESTING.md ├── access ├── AccessControl.behavior.js ├── AccessControl.test.js ├── Ownable.test.js ├── Ownable2Step.test.js ├── extensions │ ├── AccessControlDefaultAdminRules.test.js │ └── AccessControlEnumerable.test.js └── manager │ ├── AccessManaged.test.js │ ├── AccessManager.behavior.js │ ├── AccessManager.predicate.js │ ├── AccessManager.test.js │ └── AuthorityUtils.test.js ├── account ├── Account.behavior.js ├── Account.test.js ├── AccountECDSA.test.js ├── AccountERC7702.t.sol ├── AccountERC7702.test.js ├── AccountERC7913.test.js ├── AccountMultiSigner.test.js ├── AccountP256.test.js ├── AccountRSA.test.js ├── examples │ └── AccountERC7702WithModulesMock.test.js ├── extensions │ ├── AccountERC7579.behavior.js │ ├── AccountERC7579.test.js │ ├── AccountERC7579Hooked.test.js │ └── ERC7821.behavior.js └── utils │ ├── EIP7702Utils.test.js │ ├── draft-ERC4337Utils.test.js │ ├── draft-ERC7579Utils.t.sol │ └── draft-ERC7579Utils.test.js ├── bin ├── EntryPoint070.abi ├── EntryPoint070.bytecode ├── EntryPoint080.abi ├── EntryPoint080.bytecode ├── SenderCreator070.abi ├── SenderCreator070.bytecode ├── SenderCreator080.abi └── SenderCreator080.bytecode ├── finance ├── VestingWallet.behavior.js ├── VestingWallet.test.js └── VestingWalletCliff.test.js ├── governance ├── Governor.t.sol ├── Governor.test.js ├── TimelockController.test.js ├── extensions │ ├── GovernorCountingFractional.test.js │ ├── GovernorCountingOverridable.test.js │ ├── GovernorERC721.test.js │ ├── GovernorNoncesKeyed.test.js │ ├── GovernorPreventLateQuorum.test.js │ ├── GovernorProposalGuardian.test.js │ ├── GovernorSequentialProposalId.test.js │ ├── GovernorStorage.test.js │ ├── GovernorSuperQuorum.test.js │ ├── GovernorSuperQuorumGreaterThanQuorum.t.sol │ ├── GovernorTimelockAccess.test.js │ ├── GovernorTimelockCompound.test.js │ ├── GovernorTimelockControl.test.js │ ├── GovernorVotesQuorumFraction.test.js │ ├── GovernorVotesSuperQuorumFraction.test.js │ └── GovernorWithParams.test.js └── utils │ ├── ERC6372.behavior.js │ ├── Votes.behavior.js │ ├── Votes.test.js │ └── VotesExtended.test.js ├── helpers ├── access-manager.js ├── account.js ├── chains.js ├── constants.js ├── deploy.js ├── eip712-types.js ├── eip712.js ├── enums.js ├── erc4337.js ├── erc7579.js ├── erc7739.js ├── governance.js ├── iterate.js ├── math.js ├── methods.js ├── precompiles.js ├── random.js ├── signers.js ├── storage.js ├── strings.js ├── time.js └── txpool.js ├── metatx ├── ERC2771Context.test.js ├── ERC2771Forwarder.t.sol └── ERC2771Forwarder.test.js ├── proxy ├── Clones.behaviour.js ├── Clones.t.sol ├── Clones.test.js ├── ERC1967 │ ├── ERC1967Proxy.test.js │ └── ERC1967Utils.test.js ├── Proxy.behaviour.js ├── beacon │ ├── BeaconProxy.test.js │ └── UpgradeableBeacon.test.js ├── transparent │ ├── ProxyAdmin.test.js │ ├── TransparentUpgradeableProxy.behaviour.js │ └── TransparentUpgradeableProxy.test.js └── utils │ ├── Initializable.test.js │ └── UUPSUpgradeable.test.js ├── sanity.test.js ├── token ├── ERC1155 │ ├── ERC1155.behavior.js │ ├── ERC1155.test.js │ ├── extensions │ │ ├── ERC1155Burnable.test.js │ │ ├── ERC1155Pausable.test.js │ │ ├── ERC1155Supply.test.js │ │ └── ERC1155URIStorage.test.js │ └── utils │ │ ├── ERC1155Holder.test.js │ │ └── ERC1155Utils.test.js ├── ERC20 │ ├── ERC20.behavior.js │ ├── ERC20.test.js │ ├── extensions │ │ ├── ERC1363.test.js │ │ ├── ERC20Burnable.test.js │ │ ├── ERC20Capped.test.js │ │ ├── ERC20FlashMint.test.js │ │ ├── ERC20Pausable.test.js │ │ ├── ERC20Permit.test.js │ │ ├── ERC20Votes.test.js │ │ ├── ERC20Wrapper.test.js │ │ ├── ERC4626.t.sol │ │ ├── ERC4626.test.js │ │ ├── draft-ERC20Bridgeable.test.js │ │ └── draft-ERC20TemporaryApproval.test.js │ └── utils │ │ └── SafeERC20.test.js ├── ERC6909 │ ├── ERC6909.behavior.js │ ├── ERC6909.test.js │ └── extensions │ │ ├── ERC6909ContentURI.test.js │ │ ├── ERC6909Metadata.test.js │ │ └── ERC6909TokenSupply.test.js ├── ERC721 │ ├── ERC721.behavior.js │ ├── ERC721.test.js │ ├── ERC721Enumerable.test.js │ ├── extensions │ │ ├── ERC721Burnable.test.js │ │ ├── ERC721Consecutive.t.sol │ │ ├── ERC721Consecutive.test.js │ │ ├── ERC721Pausable.test.js │ │ ├── ERC721Royalty.test.js │ │ ├── ERC721URIStorage.test.js │ │ ├── ERC721Votes.test.js │ │ └── ERC721Wrapper.test.js │ └── utils │ │ ├── ERC721Holder.test.js │ │ └── ERC721Utils.test.js └── common │ └── ERC2981.behavior.js └── utils ├── Address.test.js ├── Arrays.t.sol ├── Arrays.test.js ├── Base64.t.sol ├── Base64.test.js ├── Blockhash.t.sol ├── Blockhash.test.js ├── Bytes.test.js ├── CAIP.test.js ├── Calldata.test.js ├── Context.behavior.js ├── Context.test.js ├── Create2.t.sol ├── Create2.test.js ├── Multicall.test.js ├── Nonces.behavior.js ├── Nonces.test.js ├── NoncesKeyed.test.js ├── Packing.t.sol ├── Packing.test.js ├── Panic.test.js ├── Pausable.test.js ├── ReentrancyGuard.test.js ├── ShortStrings.t.sol ├── ShortStrings.test.js ├── SlotDerivation.t.sol ├── SlotDerivation.test.js ├── StorageSlot.test.js ├── Strings.t.sol ├── Strings.test.js ├── TransientSlot.test.js ├── cryptography ├── ECDSA.test.js ├── EIP712.test.js ├── ERC1271.behavior.js ├── ERC7739.test.js ├── ERC7739Utils.test.js ├── MerkleProof.test.js ├── MessageHashUtils.t.sol ├── MessageHashUtils.test.js ├── P256.t.sol ├── P256.test.js ├── RSA.helper.js ├── RSA.test.js ├── SigVer15_186-3.rsp ├── SignatureChecker.test.js └── ecdsa_secp256r1_sha256_p1363_test.json ├── introspection ├── ERC165.test.js ├── ERC165Checker.test.js └── SupportsInterface.behavior.js ├── math ├── Math.t.sol ├── Math.test.js ├── SafeCast.test.js ├── SignedMath.t.sol └── SignedMath.test.js ├── structs ├── BitMap.test.js ├── Checkpoints.t.sol ├── Checkpoints.test.js ├── CircularBuffer.test.js ├── DoubleEndedQueue.test.js ├── EnumerableMap.behavior.js ├── EnumerableMap.test.js ├── EnumerableSet.behavior.js ├── EnumerableSet.test.js ├── Heap.t.sol ├── Heap.test.js └── MerkleTree.test.js └── types └── Time.test.js /.changeset/clean-ways-push.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `AccountERC7579`: Extension of `Account` that implements support for ERC-7579 modules of type executor, validator, and fallback handler. 6 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json", 3 | "changelog": [ 4 | "@changesets/changelog-github", 5 | { 6 | "repo": "OpenZeppelin/openzeppelin-contracts" 7 | } 8 | ], 9 | "commit": false, 10 | "access": "public", 11 | "baseBranch": "master" 12 | } 13 | -------------------------------------------------------------------------------- /.changeset/fine-frogs-bake.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `EnumerableMap`: Add `keys(uint256,uint256)` that returns a subset (slice) of the keys in the map. 6 | -------------------------------------------------------------------------------- /.changeset/full-ways-help.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `EIP7702Utils`: Add a library for checking if an address has an EIP-7702 delegation in place. 6 | -------------------------------------------------------------------------------- /.changeset/funny-years-yawn.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `Account`: Added a simple ERC-4337 account implementation with minimal logic to process user operations. 6 | -------------------------------------------------------------------------------- /.changeset/hot-grapes-lie.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `EnumerableSet`: Add `values(uint256,uint256)` that returns a subset (slice) of the values in the set. 6 | -------------------------------------------------------------------------------- /.changeset/lazy-poets-cheer.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `SignerERC7702`: Implementation of `AbstractSigner` for Externally Owned Accounts (EOAs). Useful with ERC-7702. 6 | -------------------------------------------------------------------------------- /.changeset/long-hornets-mate.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `EnumerableMap`: Add support for `BytesToBytesMap` type. 6 | -------------------------------------------------------------------------------- /.changeset/lucky-donuts-scream.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `ERC7739`: An abstract contract to validate signatures following the rehashing scheme from `ERC7739Utils`. 6 | -------------------------------------------------------------------------------- /.changeset/nice-rings-wish.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `ERC7913P256Verifier` and `ERC7913RSAVerifier`: Ready to use ERC-7913 verifiers that implement key verification for P256 (secp256r1) and RSA keys. 6 | -------------------------------------------------------------------------------- /.changeset/pink-dolls-shop.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `EnumerableSet`: Add support for `StringSet` and `BytesSet` types. 6 | -------------------------------------------------------------------------------- /.changeset/popular-geese-tan.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `GovernorNoncesKeyed`: Extension of `Governor` that adds support for keyed nonces when voting by sig. 6 | -------------------------------------------------------------------------------- /.changeset/proud-tables-sip.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `ERC7739Utils`: Add a library that implements a defensive rehashing mechanism to prevent replayability of smart contract signatures based on the ERC-7739. 6 | -------------------------------------------------------------------------------- /.changeset/quiet-kiwis-feel.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `SignerERC7913`: Abstract signer that verifies signatures using the ERC-7913 workflow. 6 | -------------------------------------------------------------------------------- /.changeset/rare-shirts-unite.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `Arrays`: Add `unsafeAccess`, `unsafeMemoryAccess` and `unsafeSetLength` for `bytes[]` and `string[]`. 6 | -------------------------------------------------------------------------------- /.changeset/ripe-bears-hide.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `ERC20Bridgeable`: Implementation of ERC-7802 that makes an ERC-20 compatible with crosschain bridges. 6 | -------------------------------------------------------------------------------- /.changeset/rotten-apes-lie.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `IERC7821`, `ERC7821`: Interface and logic for minimal batch execution. No support for additional `opData` is included. 6 | -------------------------------------------------------------------------------- /.changeset/social-walls-obey.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `MultiSignerERC7913`: Implementation of `AbstractSigner` that supports multiple ERC-7913 signers with a threshold-based signature verification system. 6 | -------------------------------------------------------------------------------- /.changeset/sour-pens-shake.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `SignatureChecker`: Add support for ERC-7913 signatures alongside existing ECDSA and ERC-1271 signature verification. 6 | -------------------------------------------------------------------------------- /.changeset/strong-points-change.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `AccountERC7579Hooked`: Extension of `AccountERC7579` that implements support for ERC-7579 hook modules. 6 | -------------------------------------------------------------------------------- /.changeset/tame-bears-mix.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `AbstractSigner`, `SignerECDSA`, `SignerP256`, and `SignerRSA`: Add an abstract contract and various implementations for contracts that deal with signature verification. 6 | -------------------------------------------------------------------------------- /.changeset/wet-dodos-reply.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'openzeppelin-solidity': minor 3 | --- 4 | 5 | `Blockhash`: Add a library that provides access to historical block hashes using EIP-2935's history storage, extending the standard 256-block limit to 8191 blocks. 6 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | comment: off 2 | github_checks: 3 | annotations: false 4 | coverage: 5 | status: 6 | patch: 7 | default: 8 | target: 95% 9 | only_pulls: true 10 | project: 11 | default: 12 | threshold: 1% 13 | ignore: 14 | - "test" 15 | - "contracts/mocks" 16 | - "contracts/vendor" 17 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | end_of_line = lf 9 | indent_style = space 10 | insert_final_newline = true 11 | trim_trailing_whitespace = false 12 | max_line_length = 120 13 | 14 | [*.sol] 15 | indent_size = 4 16 | 17 | [*.js] 18 | indent_size = 2 19 | 20 | [*.{adoc,md}] 21 | max_line_length = 0 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report a bug in OpenZeppelin Contracts 4 | 5 | --- 6 | 7 | 8 | 9 | 10 | 11 | **💻 Environment** 12 | 13 | 14 | 15 | **📝 Details** 16 | 17 | 18 | 19 | **🔢 Code to reproduce bug** 20 | 21 | 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | contact_links: 2 | - name: Questions & Support Requests 3 | url: https://forum.openzeppelin.com/c/support/contracts/18 4 | about: Ask in the OpenZeppelin Forum 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for OpenZeppelin Contracts 4 | 5 | --- 6 | 7 | **🧐 Motivation** 8 | 9 | 10 | **📝 Details** 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Fixes #???? 7 | 8 | 9 | 10 | 11 | 12 | #### PR Checklist 13 | 14 | 15 | 16 | 17 | 18 | - [ ] Tests 19 | - [ ] Documentation 20 | - [ ] Changeset entry (run `npx changeset add`) 21 | -------------------------------------------------------------------------------- /.github/actions/setup/action.yml: -------------------------------------------------------------------------------- 1 | name: Setup 2 | description: Common environment setup 3 | 4 | runs: 5 | using: composite 6 | steps: 7 | - uses: actions/setup-node@v4 8 | with: 9 | node-version: 20.x 10 | - uses: actions/cache@v4 11 | id: cache 12 | with: 13 | path: '**/node_modules' 14 | key: npm-v3-${{ hashFiles('**/package-lock.json') }} 15 | - name: Install dependencies 16 | run: npm ci 17 | shell: bash 18 | if: steps.cache.outputs.cache-hit != 'true' 19 | - name: Install Foundry 20 | uses: foundry-rs/foundry-toolchain@v1 21 | with: 22 | version: stable 23 | -------------------------------------------------------------------------------- /.github/workflows/actionlint.yml: -------------------------------------------------------------------------------- 1 | name: lint workflows 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - '.github/**/*.ya?ml' 7 | 8 | jobs: 9 | lint: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v4 13 | - name: Add problem matchers 14 | run: | 15 | # https://github.com/rhysd/actionlint/blob/3a2f2c7/docs/usage.md#problem-matchers 16 | curl -LO https://raw.githubusercontent.com/rhysd/actionlint/main/.github/actionlint-matcher.json 17 | echo "::add-matcher::actionlint-matcher.json" 18 | - uses: docker://rhysd/actionlint:latest 19 | -------------------------------------------------------------------------------- /.github/workflows/changeset.yml: -------------------------------------------------------------------------------- 1 | name: changeset 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - master 7 | types: 8 | - opened 9 | - synchronize 10 | - labeled 11 | - unlabeled 12 | 13 | concurrency: 14 | group: changeset-${{ github.ref }} 15 | cancel-in-progress: true 16 | 17 | jobs: 18 | check: 19 | runs-on: ubuntu-latest 20 | if: ${{ !contains(github.event.pull_request.labels.*.name, 'ignore-changeset') }} 21 | steps: 22 | - uses: actions/checkout@v4 23 | with: 24 | fetch-depth: 0 # Include history so Changesets finds merge-base 25 | - name: Set up environment 26 | uses: ./.github/actions/setup 27 | - name: Check changeset 28 | run: npx changeset status --since=origin/${{ github.base_ref }} 29 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Build Docs 2 | 3 | on: 4 | push: 5 | branches: [release-v*] 6 | 7 | permissions: 8 | contents: write 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | - name: Set up environment 16 | uses: ./.github/actions/setup 17 | - run: bash scripts/git-user-config.sh 18 | - run: node scripts/update-docs-branch.js 19 | - run: git push --all origin 20 | -------------------------------------------------------------------------------- /.github/workflows/upgradeable.yml: -------------------------------------------------------------------------------- 1 | name: transpile upgradeable 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - release-v* 8 | 9 | jobs: 10 | transpile: 11 | environment: push-upgradeable 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | with: 16 | repository: OpenZeppelin/openzeppelin-contracts-upgradeable 17 | fetch-depth: 0 18 | token: ${{ secrets.GH_TOKEN_UPGRADEABLE }} 19 | - name: Fetch current non-upgradeable branch 20 | run: | 21 | git fetch "$REMOTE" master # Fetch default branch first for patch to apply cleanly 22 | git fetch "$REMOTE" "$REF" 23 | git checkout FETCH_HEAD 24 | env: 25 | REF: ${{ github.ref }} 26 | REMOTE: https://github.com/${{ github.repository }}.git 27 | - name: Set up environment 28 | uses: ./.github/actions/setup 29 | - run: bash scripts/git-user-config.sh 30 | - name: Transpile to upgradeable 31 | run: bash scripts/upgradeable/transpile-onto.sh ${{ github.ref_name }} origin/${{ github.ref_name }} 32 | env: 33 | SUBMODULE_REMOTE: https://github.com/${{ github.repository }}.git 34 | - run: git push origin ${{ github.ref_name }} 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.swo 3 | 4 | # Logs 5 | logs 6 | *.log 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | allFiredEvents 13 | scTopics 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | coverage.json 18 | coverageEnv 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Dependency directory 24 | node_modules 25 | 26 | # Debug log from npm 27 | npm-debug.log 28 | 29 | # local env variables 30 | .env 31 | 32 | # macOS 33 | .DS_Store 34 | 35 | # IntelliJ IDE 36 | .idea 37 | 38 | # docs artifacts 39 | docs/modules/api 40 | build/site 41 | 42 | # only used to package @openzeppelin/contracts 43 | contracts/build/ 44 | contracts/README.md 45 | 46 | # temporary artifact from solidity-coverage 47 | allFiredEvents 48 | .coverage_artifacts 49 | .coverage_cache 50 | .coverage_contracts 51 | 52 | # hardat-exposed 53 | contracts-exposed 54 | 55 | # Hardhat 56 | /cache 57 | /artifacts 58 | 59 | # Foundry 60 | /out 61 | /cache_forge 62 | 63 | # Certora 64 | .certora* 65 | .last_confs 66 | certora_* 67 | .zip-output-url.txt 68 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/forge-std"] 2 | branch = v1 3 | path = lib/forge-std 4 | url = https://github.com/foundry-rs/forge-std 5 | [submodule "lib/erc4626-tests"] 6 | path = lib/erc4626-tests 7 | url = https://github.com/a16z/erc4626-tests.git 8 | [submodule "lib/halmos-cheatcodes"] 9 | path = lib/halmos-cheatcodes 10 | url = https://github.com/a16z/halmos-cheatcodes 11 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | npm run test:generation 2 | npx lint-staged 3 | -------------------------------------------------------------------------------- /.mocharc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | require: 'hardhat/register', 3 | timeout: 4000, 4 | }; 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "singleQuote": true, 4 | "trailingComma": "all", 5 | "arrowParens": "avoid", 6 | "overrides": [ 7 | { 8 | "files": "*.sol", 9 | "options": { 10 | "singleQuote": false 11 | } 12 | } 13 | ], 14 | "plugins": ["prettier-plugin-solidity"] 15 | } 16 | -------------------------------------------------------------------------------- /.solcover.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | norpc: true, 3 | testCommand: 'npm test', 4 | compileCommand: 'npm run compile', 5 | skipFiles: ['mocks'], 6 | providerOptions: { 7 | default_balance_ether: '10000000000000000000000000', 8 | }, 9 | mocha: { 10 | fgrep: '[skip-on-coverage]', 11 | invert: true, 12 | }, 13 | // Work around stack too deep for coverage 14 | configureYulOptimizer: true, 15 | solcOptimizerDetails: { 16 | yul: true, 17 | yulDetails: { 18 | optimizerSteps: '', 19 | }, 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /FUNDING.json: -------------------------------------------------------------------------------- 1 | { 2 | "drips": { 3 | "ethereum": { 4 | "ownedBy": "0xAeb37910f93486C85A1F8F994b67E8187554d664" 5 | } 6 | }, 7 | "opRetro": { 8 | "projectId": "0x939241afa4c4b9e1dda6b8250baa8f04fa8b0debce738cfd324c0b18f9926d25" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2025 Zeppelin Group Ltd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included 14 | in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /audits/2018-10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/audits/2018-10.pdf -------------------------------------------------------------------------------- /audits/2022-10-Checkpoints.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/audits/2022-10-Checkpoints.pdf -------------------------------------------------------------------------------- /audits/2022-10-ERC4626.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/audits/2022-10-ERC4626.pdf -------------------------------------------------------------------------------- /audits/2023-05-v4.9.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/audits/2023-05-v4.9.pdf -------------------------------------------------------------------------------- /audits/2023-10-v5.0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/audits/2023-10-v5.0.pdf -------------------------------------------------------------------------------- /audits/2024-10-v5.1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/audits/2024-10-v5.1.pdf -------------------------------------------------------------------------------- /audits/2024-12-v5.2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/audits/2024-12-v5.2.pdf -------------------------------------------------------------------------------- /audits/2025-04-v5.3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/audits/2025-04-v5.3.pdf -------------------------------------------------------------------------------- /certora/.gitignore: -------------------------------------------------------------------------------- 1 | patched 2 | -------------------------------------------------------------------------------- /certora/harnesses/AccessControlHarness.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {AccessControl} from "../patched/access/AccessControl.sol"; 5 | 6 | contract AccessControlHarness is AccessControl {} 7 | -------------------------------------------------------------------------------- /certora/harnesses/ERC20FlashMintHarness.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import "../patched/token/ERC20/ERC20.sol"; 6 | import "../patched/token/ERC20/extensions/ERC20Permit.sol"; 7 | import "../patched/token/ERC20/extensions/ERC20FlashMint.sol"; 8 | 9 | contract ERC20FlashMintHarness is ERC20, ERC20Permit, ERC20FlashMint { 10 | uint256 someFee; 11 | address someFeeReceiver; 12 | 13 | constructor(string memory name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) {} 14 | 15 | function mint(address account, uint256 amount) external { 16 | _mint(account, amount); 17 | } 18 | 19 | function burn(address account, uint256 amount) external { 20 | _burn(account, amount); 21 | } 22 | 23 | // public accessor 24 | function flashFeeReceiver() public view returns (address) { 25 | return someFeeReceiver; 26 | } 27 | 28 | // internal hook 29 | function _flashFee(address, uint256) internal view override returns (uint256) { 30 | return someFee; 31 | } 32 | 33 | function _flashFeeReceiver() internal view override returns (address) { 34 | return someFeeReceiver; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /certora/harnesses/ERC20PermitHarness.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {ERC20Permit, ERC20} from "../patched/token/ERC20/extensions/ERC20Permit.sol"; 5 | 6 | contract ERC20PermitHarness is ERC20Permit { 7 | constructor(string memory name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) {} 8 | 9 | function mint(address account, uint256 amount) external { 10 | _mint(account, amount); 11 | } 12 | 13 | function burn(address account, uint256 amount) external { 14 | _burn(account, amount); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /certora/harnesses/ERC20WrapperHarness.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC20Permit} from "../patched/token/ERC20/extensions/ERC20Permit.sol"; 6 | import {ERC20Wrapper, IERC20, ERC20} from "../patched/token/ERC20/extensions/ERC20Wrapper.sol"; 7 | 8 | contract ERC20WrapperHarness is ERC20Permit, ERC20Wrapper { 9 | constructor( 10 | IERC20 _underlying, 11 | string memory _name, 12 | string memory _symbol 13 | ) ERC20(_name, _symbol) ERC20Permit(_name) ERC20Wrapper(_underlying) {} 14 | 15 | function underlyingTotalSupply() public view returns (uint256) { 16 | return underlying().totalSupply(); 17 | } 18 | 19 | function underlyingBalanceOf(address account) public view returns (uint256) { 20 | return underlying().balanceOf(account); 21 | } 22 | 23 | function underlyingAllowanceToThis(address account) public view returns (uint256) { 24 | return underlying().allowance(account, address(this)); 25 | } 26 | 27 | function recover(address account) public returns (uint256) { 28 | return _recover(account); 29 | } 30 | 31 | function decimals() public view override(ERC20Wrapper, ERC20) returns (uint8) { 32 | return super.decimals(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /certora/harnesses/ERC3156FlashBorrowerHarness.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | import {IERC3156FlashBorrower} from "../patched/interfaces/IERC3156FlashBorrower.sol"; 4 | 5 | pragma solidity ^0.8.20; 6 | 7 | contract ERC3156FlashBorrowerHarness is IERC3156FlashBorrower { 8 | bytes32 somethingToReturn; 9 | 10 | function onFlashLoan(address, address, uint256, uint256, bytes calldata) external view override returns (bytes32) { 11 | return somethingToReturn; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /certora/harnesses/ERC721Harness.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC721} from "../patched/token/ERC721/ERC721.sol"; 6 | 7 | contract ERC721Harness is ERC721 { 8 | constructor(string memory name, string memory symbol) ERC721(name, symbol) {} 9 | 10 | function mint(address account, uint256 tokenId) external { 11 | _mint(account, tokenId); 12 | } 13 | 14 | function safeMint(address to, uint256 tokenId) external { 15 | _safeMint(to, tokenId); 16 | } 17 | 18 | function safeMint(address to, uint256 tokenId, bytes memory data) external { 19 | _safeMint(to, tokenId, data); 20 | } 21 | 22 | function burn(uint256 tokenId) external { 23 | _burn(tokenId); 24 | } 25 | 26 | function unsafeOwnerOf(uint256 tokenId) external view returns (address) { 27 | return _ownerOf(tokenId); 28 | } 29 | 30 | function unsafeGetApproved(uint256 tokenId) external view returns (address) { 31 | return _getApproved(tokenId); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /certora/harnesses/ERC721ReceiverHarness.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import "../patched/interfaces/IERC721Receiver.sol"; 6 | 7 | contract ERC721ReceiverHarness is IERC721Receiver { 8 | function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) { 9 | return this.onERC721Received.selector; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /certora/harnesses/EnumerableSetHarness.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {EnumerableSet} from "../patched/utils/structs/EnumerableSet.sol"; 6 | 7 | contract EnumerableSetHarness { 8 | using EnumerableSet for EnumerableSet.Bytes32Set; 9 | 10 | EnumerableSet.Bytes32Set private _set; 11 | 12 | function add(bytes32 value) public returns (bool) { 13 | return _set.add(value); 14 | } 15 | 16 | function remove(bytes32 value) public returns (bool) { 17 | return _set.remove(value); 18 | } 19 | 20 | function contains(bytes32 value) public view returns (bool) { 21 | return _set.contains(value); 22 | } 23 | 24 | function length() public view returns (uint256) { 25 | return _set.length(); 26 | } 27 | 28 | function at_(uint256 index) public view returns (bytes32) { 29 | return _set.at(index); 30 | } 31 | 32 | function _positionOf(bytes32 value) public view returns (uint256) { 33 | return _set._inner._positions[value]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /certora/harnesses/InitializableHarness.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {Initializable} from "../patched/proxy/utils/Initializable.sol"; 5 | 6 | contract InitializableHarness is Initializable { 7 | function initialize() public initializer {} 8 | function reinitialize(uint64 n) public reinitializer(n) {} 9 | function disable() public { _disableInitializers(); } 10 | 11 | function nested_init_init() public initializer { initialize(); } 12 | function nested_init_reinit(uint64 m) public initializer { reinitialize(m); } 13 | function nested_reinit_init(uint64 n) public reinitializer(n) { initialize(); } 14 | function nested_reinit_reinit(uint64 n, uint64 m) public reinitializer(n) { reinitialize(m); } 15 | 16 | function version() public view returns (uint64) { 17 | return _getInitializedVersion(); 18 | } 19 | 20 | function initializing() public view returns (bool) { 21 | return _isInitializing(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /certora/harnesses/NoncesHarness.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {Nonces} from "../patched/utils/Nonces.sol"; 5 | 6 | contract NoncesHarness is Nonces { 7 | function useNonce(address account) external returns (uint256) { 8 | return _useNonce(account); 9 | } 10 | 11 | function useCheckedNonce(address account, uint256 nonce) external { 12 | _useCheckedNonce(account, nonce); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /certora/harnesses/Ownable2StepHarness.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {Ownable2Step, Ownable} from "../patched/access/Ownable2Step.sol"; 5 | 6 | contract Ownable2StepHarness is Ownable2Step { 7 | constructor(address initialOwner) Ownable(initialOwner) {} 8 | 9 | function restricted() external onlyOwner {} 10 | } 11 | -------------------------------------------------------------------------------- /certora/harnesses/OwnableHarness.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {Ownable} from "../patched/access/Ownable.sol"; 5 | 6 | contract OwnableHarness is Ownable { 7 | constructor(address initialOwner) Ownable(initialOwner) {} 8 | 9 | function restricted() external onlyOwner {} 10 | } 11 | -------------------------------------------------------------------------------- /certora/harnesses/PausableHarness.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {Pausable} from "../patched/utils/Pausable.sol"; 5 | 6 | contract PausableHarness is Pausable { 7 | function pause() external { 8 | _pause(); 9 | } 10 | 11 | function unpause() external { 12 | _unpause(); 13 | } 14 | 15 | function onlyWhenPaused() external whenPaused {} 16 | 17 | function onlyWhenNotPaused() external whenNotPaused {} 18 | } 19 | -------------------------------------------------------------------------------- /certora/harnesses/TimelockControllerHarness.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {TimelockController} from "../patched/governance/TimelockController.sol"; 5 | 6 | contract TimelockControllerHarness is TimelockController { 7 | constructor( 8 | uint256 minDelay, 9 | address[] memory proposers, 10 | address[] memory executors, 11 | address admin 12 | ) TimelockController(minDelay, proposers, executors, admin) {} 13 | } 14 | -------------------------------------------------------------------------------- /certora/reports/2021-10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/certora/reports/2021-10.pdf -------------------------------------------------------------------------------- /certora/reports/2022-03.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/certora/reports/2022-03.pdf -------------------------------------------------------------------------------- /certora/reports/2022-05.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/certora/reports/2022-05.pdf -------------------------------------------------------------------------------- /certora/specs/AccessManaged.spec: -------------------------------------------------------------------------------- 1 | import "helpers/helpers.spec"; 2 | import "methods/IAccessManaged.spec"; 3 | 4 | methods { 5 | // FV 6 | function someFunction() external; 7 | function authority_canCall_immediate(address) external returns (bool); 8 | function authority_canCall_delay(address) external returns (uint32); 9 | function authority_getSchedule(address) external returns (uint48); 10 | } 11 | 12 | invariant isConsumingScheduledOpClean() 13 | isConsumingScheduledOp() == to_bytes4(0); 14 | 15 | rule callRestrictedFunction(env e) { 16 | bool immediate = authority_canCall_immediate(e, e.msg.sender); 17 | uint32 delay = authority_canCall_delay(e, e.msg.sender); 18 | uint48 scheduleBefore = authority_getSchedule(e, e.msg.sender); 19 | 20 | someFunction@withrevert(e); 21 | bool success = !lastReverted; 22 | 23 | uint48 scheduleAfter = authority_getSchedule(e, e.msg.sender); 24 | 25 | // can only call if immediate, or (with delay) by consuming a scheduled op 26 | assert success => ( 27 | immediate || 28 | ( 29 | delay > 0 && 30 | isSetAndPast(e, scheduleBefore) && 31 | scheduleAfter == 0 32 | ) 33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /certora/specs/helpers/helpers.spec: -------------------------------------------------------------------------------- 1 | // environment 2 | definition nonpayable(env e) returns bool = e.msg.value == 0; 3 | definition nonzerosender(env e) returns bool = e.msg.sender != 0; 4 | definition sanity(env e) returns bool = clock(e) > 0 && clock(e) <= max_uint48; 5 | 6 | // math 7 | definition min(mathint a, mathint b) returns mathint = a < b ? a : b; 8 | definition max(mathint a, mathint b) returns mathint = a > b ? a : b; 9 | 10 | // time 11 | definition clock(env e) returns mathint = to_mathint(e.block.timestamp); 12 | definition isSetAndPast(env e, uint48 timepoint) returns bool = timepoint != 0 && to_mathint(timepoint) <= clock(e); 13 | -------------------------------------------------------------------------------- /certora/specs/methods/IAccessControl.spec: -------------------------------------------------------------------------------- 1 | methods { 2 | function DEFAULT_ADMIN_ROLE() external returns (bytes32) envfree; 3 | function hasRole(bytes32, address) external returns(bool) envfree; 4 | function getRoleAdmin(bytes32) external returns(bytes32) envfree; 5 | function grantRole(bytes32, address) external; 6 | function revokeRole(bytes32, address) external; 7 | function renounceRole(bytes32, address) external; 8 | } 9 | -------------------------------------------------------------------------------- /certora/specs/methods/IAccessControlDefaultAdminRules.spec: -------------------------------------------------------------------------------- 1 | import "./IERC5313.spec"; 2 | 3 | methods { 4 | // === View == 5 | 6 | // Default Admin 7 | function defaultAdmin() external returns(address) envfree; 8 | function pendingDefaultAdmin() external returns(address, uint48) envfree; 9 | 10 | // Default Admin Delay 11 | function defaultAdminDelay() external returns(uint48); 12 | function pendingDefaultAdminDelay() external returns(uint48, uint48); 13 | function defaultAdminDelayIncreaseWait() external returns(uint48) envfree; 14 | 15 | // === Mutations == 16 | 17 | // Default Admin 18 | function beginDefaultAdminTransfer(address) external; 19 | function cancelDefaultAdminTransfer() external; 20 | function acceptDefaultAdminTransfer() external; 21 | 22 | // Default Admin Delay 23 | function changeDefaultAdminDelay(uint48) external; 24 | function rollbackDefaultAdminDelay() external; 25 | 26 | // == FV == 27 | 28 | // Default Admin 29 | function pendingDefaultAdmin_() external returns (address) envfree; 30 | function pendingDefaultAdminSchedule_() external returns (uint48) envfree; 31 | 32 | // Default Admin Delay 33 | function pendingDelay_() external returns (uint48); 34 | function pendingDelaySchedule_() external returns (uint48); 35 | function delayChangeWait_(uint48) external returns (uint48); 36 | } 37 | -------------------------------------------------------------------------------- /certora/specs/methods/IAccessManaged.spec: -------------------------------------------------------------------------------- 1 | methods { 2 | function authority() external returns (address) envfree; 3 | function isConsumingScheduledOp() external returns (bytes4) envfree; 4 | function setAuthority(address) external; 5 | } 6 | -------------------------------------------------------------------------------- /certora/specs/methods/IERC20.spec: -------------------------------------------------------------------------------- 1 | methods { 2 | function name() external returns (string) envfree; 3 | function symbol() external returns (string) envfree; 4 | function decimals() external returns (uint8) envfree; 5 | function totalSupply() external returns (uint256) envfree; 6 | function balanceOf(address) external returns (uint256) envfree; 7 | function allowance(address,address) external returns (uint256) envfree; 8 | function approve(address,uint256) external returns (bool); 9 | function transfer(address,uint256) external returns (bool); 10 | function transferFrom(address,address,uint256) external returns (bool); 11 | } 12 | -------------------------------------------------------------------------------- /certora/specs/methods/IERC2612.spec: -------------------------------------------------------------------------------- 1 | methods { 2 | function permit(address,address,uint256,uint256,uint8,bytes32,bytes32) external; 3 | function nonces(address) external returns (uint256) envfree; 4 | function DOMAIN_SEPARATOR() external returns (bytes32) envfree; 5 | } 6 | -------------------------------------------------------------------------------- /certora/specs/methods/IERC3156FlashBorrower.spec: -------------------------------------------------------------------------------- 1 | methods { 2 | function _.onFlashLoan(address,address,uint256,uint256,bytes) external => DISPATCHER(true); 3 | } 4 | -------------------------------------------------------------------------------- /certora/specs/methods/IERC3156FlashLender.spec: -------------------------------------------------------------------------------- 1 | methods { 2 | function maxFlashLoan(address) external returns (uint256) envfree; 3 | function flashFee(address,uint256) external returns (uint256) envfree; 4 | function flashLoan(address,address,uint256,bytes) external returns (bool); 5 | } 6 | -------------------------------------------------------------------------------- /certora/specs/methods/IERC5313.spec: -------------------------------------------------------------------------------- 1 | methods { 2 | function owner() external returns (address) envfree; 3 | } 4 | -------------------------------------------------------------------------------- /certora/specs/methods/IERC721.spec: -------------------------------------------------------------------------------- 1 | methods { 2 | // IERC721 3 | function balanceOf(address) external returns (uint256) envfree; 4 | function ownerOf(uint256) external returns (address) envfree; 5 | function getApproved(uint256) external returns (address) envfree; 6 | function isApprovedForAll(address,address) external returns (bool) envfree; 7 | function safeTransferFrom(address,address,uint256,bytes) external; 8 | function safeTransferFrom(address,address,uint256) external; 9 | function transferFrom(address,address,uint256) external; 10 | function approve(address,uint256) external; 11 | function setApprovalForAll(address,bool) external; 12 | 13 | // IERC721Metadata 14 | function name() external returns (string); 15 | function symbol() external returns (string); 16 | function tokenURI(uint256) external returns (string); 17 | } 18 | -------------------------------------------------------------------------------- /certora/specs/methods/IERC721Receiver.spec: -------------------------------------------------------------------------------- 1 | methods { 2 | function _.onERC721Received(address,address,uint256,bytes) external => DISPATCHER(true); 3 | } 4 | -------------------------------------------------------------------------------- /certora/specs/methods/IOwnable.spec: -------------------------------------------------------------------------------- 1 | methods { 2 | function owner() external returns (address) envfree; 3 | function transferOwnership(address) external; 4 | function renounceOwnership() external; 5 | } 6 | -------------------------------------------------------------------------------- /certora/specs/methods/IOwnable2Step.spec: -------------------------------------------------------------------------------- 1 | methods { 2 | function owner() external returns (address) envfree; 3 | function pendingOwner() external returns (address) envfree; 4 | function transferOwnership(address) external; 5 | function acceptOwnership() external; 6 | function renounceOwnership() external; 7 | } 8 | -------------------------------------------------------------------------------- /contracts/access/manager/IAccessManaged.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (access/manager/IAccessManaged.sol) 3 | 4 | pragma solidity >=0.8.4; 5 | 6 | interface IAccessManaged { 7 | /** 8 | * @dev Authority that manages this contract was updated. 9 | */ 10 | event AuthorityUpdated(address authority); 11 | 12 | error AccessManagedUnauthorized(address caller); 13 | error AccessManagedRequiredDelay(address caller, uint32 delay); 14 | error AccessManagedInvalidAuthority(address authority); 15 | 16 | /** 17 | * @dev Returns the current authority. 18 | */ 19 | function authority() external view returns (address); 20 | 21 | /** 22 | * @dev Transfers control to a new authority. The caller must be the current authority. 23 | */ 24 | function setAuthority(address) external; 25 | 26 | /** 27 | * @dev Returns true only in the context of a delayed restricted call, at the moment that the scheduled operation is 28 | * being consumed. Prevents denial of service for delayed restricted calls in the case that the contract performs 29 | * attacker controlled calls. 30 | */ 31 | function isConsumingScheduledOp() external view returns (bytes4); 32 | } 33 | -------------------------------------------------------------------------------- /contracts/access/manager/IAuthority.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (access/manager/IAuthority.sol) 3 | 4 | pragma solidity >=0.4.16; 5 | 6 | /** 7 | * @dev Standard interface for permissioning originally defined in Dappsys. 8 | */ 9 | interface IAuthority { 10 | /** 11 | * @dev Returns true if the caller can invoke on a target the function identified by a function selector. 12 | */ 13 | function canCall(address caller, address target, bytes4 selector) external view returns (bool allowed); 14 | } 15 | -------------------------------------------------------------------------------- /contracts/account/README.adoc: -------------------------------------------------------------------------------- 1 | = Account 2 | [.readme-notice] 3 | NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/account 4 | 5 | This directory includes contracts to build accounts for ERC-4337. These include: 6 | 7 | * {Account}: An ERC-4337 smart account implementation that includes the core logic to process user operations. 8 | * {AccountERC7579}: An extension of `Account` that implements support for ERC-7579 modules. 9 | * {AccountERC7579Hooked}: An extension of `AccountERC7579` with support for a single hook module (type 4). 10 | * {ERC7821}: Minimal batch executor implementation contracts. Useful to enable easy batch execution for smart contracts. 11 | * {ERC4337Utils}: Utility functions for working with ERC-4337 user operations. 12 | * {ERC7579Utils}: Utility functions for working with ERC-7579 modules and account modularity. 13 | 14 | == Core 15 | 16 | {{Account}} 17 | 18 | == Extensions 19 | 20 | {{AccountERC7579}} 21 | 22 | {{AccountERC7579Hooked}} 23 | 24 | {{ERC7821}} 25 | 26 | == Utilities 27 | 28 | {{ERC4337Utils}} 29 | 30 | {{ERC7579Utils}} 31 | -------------------------------------------------------------------------------- /contracts/account/utils/EIP7702Utils.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | /** 6 | * @dev Library with common EIP-7702 utility functions. 7 | * 8 | * See https://eips.ethereum.org/EIPS/eip-7702[ERC-7702]. 9 | */ 10 | library EIP7702Utils { 11 | bytes3 internal constant EIP7702_PREFIX = 0xef0100; 12 | 13 | /** 14 | * @dev Returns the address of the delegate if `account` as an EIP-7702 delegation setup, or address(0) otherwise. 15 | */ 16 | function fetchDelegate(address account) internal view returns (address) { 17 | bytes23 delegation = bytes23(account.code); 18 | return bytes3(delegation) == EIP7702_PREFIX ? address(bytes20(delegation << 24)) : address(0); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /contracts/finance/README.adoc: -------------------------------------------------------------------------------- 1 | = Finance 2 | 3 | [.readme-notice] 4 | NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/finance 5 | 6 | This directory includes primitives for financial systems: 7 | 8 | - {VestingWallet} handles the vesting of Ether and ERC-20 tokens for a given beneficiary. Custody of multiple tokens can 9 | be given to this contract, which will release the token to the beneficiary following a given, customizable, vesting 10 | schedule. 11 | 12 | == Contracts 13 | 14 | {{VestingWallet}} 15 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC1155.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1155.sol) 3 | 4 | pragma solidity >=0.6.2; 5 | 6 | import {IERC1155} from "../token/ERC1155/IERC1155.sol"; 7 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC1155MetadataURI.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1155MetadataURI.sol) 3 | 4 | pragma solidity >=0.6.2; 5 | 6 | import {IERC1155MetadataURI} from "../token/ERC1155/extensions/IERC1155MetadataURI.sol"; 7 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC1155Receiver.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1155Receiver.sol) 3 | 4 | pragma solidity >=0.6.2; 5 | 6 | import {IERC1155Receiver} from "../token/ERC1155/IERC1155Receiver.sol"; 7 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC1271.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.3.0) (interfaces/IERC1271.sol) 3 | 4 | pragma solidity >=0.5.0; 5 | 6 | /** 7 | * @dev Interface of the ERC-1271 standard signature validation method for 8 | * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. 9 | */ 10 | interface IERC1271 { 11 | /** 12 | * @dev Should return whether the signature provided is valid for the provided data 13 | * @param hash Hash of the data to be signed 14 | * @param signature Signature byte array associated with `hash` 15 | */ 16 | function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4 magicValue); 17 | } 18 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC1363Spender.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363Spender.sol) 3 | 4 | pragma solidity >=0.5.0; 5 | 6 | /** 7 | * @title IERC1363Spender 8 | * @dev Interface for any contract that wants to support `approveAndCall` 9 | * from ERC-1363 token contracts. 10 | */ 11 | interface IERC1363Spender { 12 | /** 13 | * @dev Whenever an ERC-1363 token `owner` approves this contract via `approveAndCall` 14 | * to spend their tokens, this function is called. 15 | * 16 | * NOTE: To accept the approval, this must return 17 | * `bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))` 18 | * (i.e. 0x7b04a2d0, or its own function selector). 19 | * 20 | * @param owner The address which called `approveAndCall` function and previously owned the tokens. 21 | * @param value The amount of tokens to be spent. 22 | * @param data Additional data with no specified format. 23 | * @return `bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))` if approval is allowed unless throwing. 24 | */ 25 | function onApprovalReceived(address owner, uint256 value, bytes calldata data) external returns (bytes4); 26 | } 27 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC165.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol) 3 | 4 | pragma solidity >=0.4.16; 5 | 6 | import {IERC165} from "../utils/introspection/IERC165.sol"; 7 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC1820Implementer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1820Implementer.sol) 3 | 4 | pragma solidity >=0.4.16; 5 | 6 | /** 7 | * @dev Interface for an ERC-1820 implementer, as defined in the 8 | * https://eips.ethereum.org/EIPS/eip-1820#interface-implementation-erc1820implementerinterface[ERC]. 9 | * Used by contracts that will be registered as implementers in the 10 | * {IERC1820Registry}. 11 | */ 12 | interface IERC1820Implementer { 13 | /** 14 | * @dev Returns a special value (`ERC1820_ACCEPT_MAGIC`) if this contract 15 | * implements `interfaceHash` for `account`. 16 | * 17 | * See {IERC1820Registry-setInterfaceImplementer}. 18 | */ 19 | function canImplementInterfaceForAddress(bytes32 interfaceHash, address account) external view returns (bytes32); 20 | } 21 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC1967.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol) 3 | 4 | pragma solidity >=0.4.11; 5 | 6 | /** 7 | * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. 8 | */ 9 | interface IERC1967 { 10 | /** 11 | * @dev Emitted when the implementation is upgraded. 12 | */ 13 | event Upgraded(address indexed implementation); 14 | 15 | /** 16 | * @dev Emitted when the admin account has changed. 17 | */ 18 | event AdminChanged(address previousAdmin, address newAdmin); 19 | 20 | /** 21 | * @dev Emitted when the beacon is changed. 22 | */ 23 | event BeaconUpgraded(address indexed beacon); 24 | } 25 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol) 3 | 4 | pragma solidity >=0.4.16; 5 | 6 | import {IERC20} from "../token/ERC20/IERC20.sol"; 7 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC20Metadata.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20Metadata.sol) 3 | 4 | pragma solidity >=0.6.2; 5 | 6 | import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol"; 7 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC2309.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC2309.sol) 3 | 4 | pragma solidity >=0.4.11; 5 | 6 | /** 7 | * @dev ERC-2309: ERC-721 Consecutive Transfer Extension. 8 | */ 9 | interface IERC2309 { 10 | /** 11 | * @dev Emitted when the tokens from `fromTokenId` to `toTokenId` are transferred from `fromAddress` to `toAddress`. 12 | */ 13 | event ConsecutiveTransfer( 14 | uint256 indexed fromTokenId, 15 | uint256 toTokenId, 16 | address indexed fromAddress, 17 | address indexed toAddress 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC2612.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC2612.sol) 3 | 4 | pragma solidity >=0.6.2; 5 | 6 | import {IERC20Permit} from "../token/ERC20/extensions/IERC20Permit.sol"; 7 | 8 | interface IERC2612 is IERC20Permit {} 9 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC2981.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC2981.sol) 3 | 4 | pragma solidity >=0.6.2; 5 | 6 | import {IERC165} from "../utils/introspection/IERC165.sol"; 7 | 8 | /** 9 | * @dev Interface for the NFT Royalty Standard. 10 | * 11 | * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal 12 | * support for royalty payments across all NFT marketplaces and ecosystem participants. 13 | */ 14 | interface IERC2981 is IERC165 { 15 | /** 16 | * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of 17 | * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. 18 | * 19 | * NOTE: ERC-2981 allows setting the royalty to 100% of the price. In that case all the price would be sent to the 20 | * royalty receiver and 0 tokens to the seller. Contracts dealing with royalty should consider empty transfers. 21 | */ 22 | function royaltyInfo( 23 | uint256 tokenId, 24 | uint256 salePrice 25 | ) external view returns (address receiver, uint256 royaltyAmount); 26 | } 27 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC3156.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC3156.sol) 3 | 4 | pragma solidity >=0.5.0; 5 | 6 | import {IERC3156FlashBorrower} from "./IERC3156FlashBorrower.sol"; 7 | import {IERC3156FlashLender} from "./IERC3156FlashLender.sol"; 8 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC3156FlashBorrower.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC3156FlashBorrower.sol) 3 | 4 | pragma solidity >=0.5.0; 5 | 6 | /** 7 | * @dev Interface of the ERC-3156 FlashBorrower, as defined in 8 | * https://eips.ethereum.org/EIPS/eip-3156[ERC-3156]. 9 | */ 10 | interface IERC3156FlashBorrower { 11 | /** 12 | * @dev Receive a flash loan. 13 | * @param initiator The initiator of the loan. 14 | * @param token The loan currency. 15 | * @param amount The amount of tokens lent. 16 | * @param fee The additional amount of tokens to repay. 17 | * @param data Arbitrary data structure, intended to contain user-defined parameters. 18 | * @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan" 19 | */ 20 | function onFlashLoan( 21 | address initiator, 22 | address token, 23 | uint256 amount, 24 | uint256 fee, 25 | bytes calldata data 26 | ) external returns (bytes32); 27 | } 28 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC4906.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC4906.sol) 3 | 4 | pragma solidity >=0.6.2; 5 | 6 | import {IERC165} from "./IERC165.sol"; 7 | import {IERC721} from "./IERC721.sol"; 8 | 9 | /// @title ERC-721 Metadata Update Extension 10 | interface IERC4906 is IERC165, IERC721 { 11 | /// @dev This event emits when the metadata of a token is changed. 12 | /// So that the third-party platforms such as NFT market could 13 | /// timely update the images and related attributes of the NFT. 14 | event MetadataUpdate(uint256 _tokenId); 15 | 16 | /// @dev This event emits when the metadata of a range of tokens is changed. 17 | /// So that the third-party platforms such as NFT market could 18 | /// timely update the images and related attributes of the NFTs. 19 | event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId); 20 | } 21 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC5267.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol) 3 | 4 | pragma solidity >=0.4.16; 5 | 6 | interface IERC5267 { 7 | /** 8 | * @dev MAY be emitted to signal that the domain could have changed. 9 | */ 10 | event EIP712DomainChanged(); 11 | 12 | /** 13 | * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 14 | * signature. 15 | */ 16 | function eip712Domain() 17 | external 18 | view 19 | returns ( 20 | bytes1 fields, 21 | string memory name, 22 | string memory version, 23 | uint256 chainId, 24 | address verifyingContract, 25 | bytes32 salt, 26 | uint256[] memory extensions 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC5313.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5313.sol) 3 | 4 | pragma solidity >=0.4.16; 5 | 6 | /** 7 | * @dev Interface for the Light Contract Ownership Standard. 8 | * 9 | * A standardized minimal interface required to identify an account that controls a contract 10 | */ 11 | interface IERC5313 { 12 | /** 13 | * @dev Gets the address of the owner. 14 | */ 15 | function owner() external view returns (address); 16 | } 17 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC5805.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5805.sol) 3 | 4 | pragma solidity >=0.8.4; 5 | 6 | import {IVotes} from "../governance/utils/IVotes.sol"; 7 | import {IERC6372} from "./IERC6372.sol"; 8 | 9 | interface IERC5805 is IERC6372, IVotes {} 10 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC6372.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC6372.sol) 3 | 4 | pragma solidity >=0.4.16; 5 | 6 | interface IERC6372 { 7 | /** 8 | * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting). 9 | */ 10 | function clock() external view returns (uint48); 11 | 12 | /** 13 | * @dev Description of the clock 14 | */ 15 | // solhint-disable-next-line func-name-mixedcase 16 | function CLOCK_MODE() external view returns (string memory); 17 | } 18 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC721.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC721.sol) 3 | 4 | pragma solidity >=0.6.2; 5 | 6 | import {IERC721} from "../token/ERC721/IERC721.sol"; 7 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC721Enumerable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC721Enumerable.sol) 3 | 4 | pragma solidity >=0.6.2; 5 | 6 | import {IERC721Enumerable} from "../token/ERC721/extensions/IERC721Enumerable.sol"; 7 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC721Metadata.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC721Metadata.sol) 3 | 4 | pragma solidity >=0.6.2; 5 | 6 | import {IERC721Metadata} from "../token/ERC721/extensions/IERC721Metadata.sol"; 7 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC721Receiver.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC721Receiver.sol) 3 | 4 | pragma solidity >=0.5.0; 5 | 6 | import {IERC721Receiver} from "../token/ERC721/IERC721Receiver.sol"; 7 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC7913.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity >=0.5.0; 4 | 5 | /** 6 | * @dev Signature verifier interface. 7 | */ 8 | interface IERC7913SignatureVerifier { 9 | /** 10 | * @dev Verifies `signature` as a valid signature of `hash` by `key`. 11 | * 12 | * MUST return the bytes4 magic value IERC7913SignatureVerifier.verify.selector if the signature is valid. 13 | * SHOULD return 0xffffffff or revert if the signature is not valid. 14 | * SHOULD return 0xffffffff or revert if the key is empty 15 | */ 16 | function verify(bytes calldata key, bytes32 hash, bytes calldata signature) external view returns (bytes4); 17 | } 18 | -------------------------------------------------------------------------------- /contracts/interfaces/draft-IERC1822.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol) 3 | 4 | pragma solidity >=0.4.16; 5 | 6 | /** 7 | * @dev ERC-1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified 8 | * proxy whose upgrades are fully controlled by the current implementation. 9 | */ 10 | interface IERC1822Proxiable { 11 | /** 12 | * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation 13 | * address. 14 | * 15 | * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks 16 | * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this 17 | * function revert if invoked through a proxy. 18 | */ 19 | function proxiableUUID() external view returns (bytes32); 20 | } 21 | -------------------------------------------------------------------------------- /contracts/interfaces/draft-IERC7674.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC7674.sol) 3 | 4 | pragma solidity >=0.6.2; 5 | 6 | import {IERC20} from "./IERC20.sol"; 7 | 8 | /** 9 | * @dev Temporary Approval Extension for ERC-20 (https://github.com/ethereum/ERCs/pull/358[ERC-7674]) 10 | */ 11 | interface IERC7674 is IERC20 { 12 | /** 13 | * @dev Set the temporary allowance, allowing `spender` to withdraw (within the same transaction) assets 14 | * held by the caller. 15 | */ 16 | function temporaryApprove(address spender, uint256 value) external returns (bool success); 17 | } 18 | -------------------------------------------------------------------------------- /contracts/metatx/README.adoc: -------------------------------------------------------------------------------- 1 | = Meta Transactions 2 | 3 | [.readme-notice] 4 | NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/metatx 5 | 6 | This directory includes contracts for adding meta-transaction capabilities (i.e. abstracting the execution context from the transaction origin) following the https://eips.ethereum.org/EIPS/eip-2771[ERC-2771 specification]. 7 | 8 | - {ERC2771Context}: Provides a mechanism to override the sender and calldata of the execution context (`msg.sender` and `msg.data`) with a custom value specified by a trusted forwarder. 9 | - {ERC2771Forwarder}: A production-ready forwarder that relays operation requests signed off-chain by an EOA. 10 | 11 | == Core 12 | 13 | {{ERC2771Context}} 14 | 15 | == Utils 16 | 17 | {{ERC2771Forwarder}} 18 | -------------------------------------------------------------------------------- /contracts/mocks/AccessManagedTarget.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {AccessManaged} from "../access/manager/AccessManaged.sol"; 6 | import {StorageSlot} from "../utils/StorageSlot.sol"; 7 | 8 | abstract contract AccessManagedTarget is AccessManaged { 9 | event CalledRestricted(address caller); 10 | event CalledUnrestricted(address caller); 11 | event CalledFallback(address caller); 12 | 13 | function fnRestricted() public restricted { 14 | emit CalledRestricted(msg.sender); 15 | } 16 | 17 | function fnUnrestricted() public { 18 | emit CalledUnrestricted(msg.sender); 19 | } 20 | 21 | function setIsConsumingScheduledOp(bool isConsuming, bytes32 slot) external { 22 | // Memory layout is 0x....<_consumingSchedule (boolean)> 23 | bytes32 mask = bytes32(uint256(1 << 160)); 24 | if (isConsuming) { 25 | StorageSlot.getBytes32Slot(slot).value |= mask; 26 | } else { 27 | StorageSlot.getBytes32Slot(slot).value &= ~mask; 28 | } 29 | } 30 | 31 | fallback() external { 32 | emit CalledFallback(msg.sender); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /contracts/mocks/AccessManagerMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {AccessManager} from "../access/manager/AccessManager.sol"; 6 | 7 | contract AccessManagerMock is AccessManager { 8 | event CalledRestricted(address caller); 9 | event CalledUnrestricted(address caller); 10 | 11 | constructor(address initialAdmin) AccessManager(initialAdmin) {} 12 | 13 | function fnRestricted() public onlyAuthorized { 14 | emit CalledRestricted(msg.sender); 15 | } 16 | 17 | function fnUnrestricted() public { 18 | emit CalledUnrestricted(msg.sender); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /contracts/mocks/Base64Dirty.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {Base64} from "../utils/Base64.sol"; 6 | 7 | contract Base64Dirty { 8 | struct A { 9 | uint256 value; 10 | } 11 | 12 | function encode(bytes memory input) public pure returns (string memory) { 13 | A memory unused = A({value: type(uint256).max}); 14 | // To silence warning 15 | unused; 16 | 17 | return Base64.encode(input); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/mocks/BatchCaller.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {Address} from "../utils/Address.sol"; 5 | 6 | contract BatchCaller { 7 | struct Call { 8 | address target; 9 | uint256 value; 10 | bytes data; 11 | } 12 | 13 | function execute(Call[] calldata calls) external returns (bytes[] memory) { 14 | bytes[] memory returndata = new bytes[](calls.length); 15 | for (uint256 i = 0; i < calls.length; ++i) { 16 | returndata[i] = Address.functionCallWithValue(calls[i].target, calls[i].data, calls[i].value); 17 | } 18 | return returndata; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /contracts/mocks/ConstructorMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | contract ConstructorMock { 6 | bool foo; 7 | 8 | enum RevertType { 9 | None, 10 | RevertWithoutMessage, 11 | RevertWithMessage, 12 | RevertWithCustomError, 13 | Panic 14 | } 15 | 16 | error CustomError(); 17 | 18 | constructor(RevertType error) { 19 | // After transpilation to upgradeable contract, the constructor will become an initializer 20 | // To silence the `... can be restricted to view` warning, we write to state 21 | foo = true; 22 | 23 | if (error == RevertType.RevertWithoutMessage) { 24 | revert(); 25 | } else if (error == RevertType.RevertWithMessage) { 26 | revert("ConstructorMock: reverting"); 27 | } else if (error == RevertType.RevertWithCustomError) { 28 | revert CustomError(); 29 | } else if (error == RevertType.Panic) { 30 | uint256 a = uint256(0) / uint256(0); 31 | a; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /contracts/mocks/ContextMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {Context} from "../utils/Context.sol"; 6 | 7 | contract ContextMock is Context { 8 | event Sender(address sender); 9 | 10 | function msgSender() public { 11 | emit Sender(_msgSender()); 12 | } 13 | 14 | event Data(bytes data, uint256 integerValue, string stringValue); 15 | 16 | function msgData(uint256 integerValue, string memory stringValue) public { 17 | emit Data(_msgData(), integerValue, stringValue); 18 | } 19 | 20 | event DataShort(bytes data); 21 | 22 | function msgDataShort() public { 23 | emit DataShort(_msgData()); 24 | } 25 | } 26 | 27 | contract ContextMockCaller { 28 | function callSender(ContextMock context) public { 29 | context.msgSender(); 30 | } 31 | 32 | function callData(ContextMock context, uint256 integerValue, string memory stringValue) public { 33 | context.msgData(integerValue, stringValue); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /contracts/mocks/EIP712Verifier.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ECDSA} from "../utils/cryptography/ECDSA.sol"; 6 | import {EIP712} from "../utils/cryptography/EIP712.sol"; 7 | 8 | abstract contract EIP712Verifier is EIP712 { 9 | function verify(bytes memory signature, address signer, address mailTo, string memory mailContents) external view { 10 | bytes32 digest = _hashTypedDataV4( 11 | keccak256(abi.encode(keccak256("Mail(address to,string contents)"), mailTo, keccak256(bytes(mailContents)))) 12 | ); 13 | address recoveredSigner = ECDSA.recover(digest, signature); 14 | require(recoveredSigner == signer); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /contracts/mocks/ERC1271WalletMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {Ownable} from "../access/Ownable.sol"; 6 | import {IERC1271} from "../interfaces/IERC1271.sol"; 7 | import {ECDSA} from "../utils/cryptography/ECDSA.sol"; 8 | 9 | contract ERC1271WalletMock is Ownable, IERC1271 { 10 | constructor(address originalOwner) Ownable(originalOwner) {} 11 | 12 | function isValidSignature(bytes32 hash, bytes memory signature) public view returns (bytes4 magicValue) { 13 | return ECDSA.recover(hash, signature) == owner() ? this.isValidSignature.selector : bytes4(0); 14 | } 15 | } 16 | 17 | contract ERC1271MaliciousMock is IERC1271 { 18 | function isValidSignature(bytes32, bytes memory) public pure returns (bytes4) { 19 | assembly { 20 | mstore(0, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) 21 | return(0, 32) 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /contracts/mocks/ERC165/ERC165MaliciousData.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | contract ERC165MaliciousData { 6 | function supportsInterface(bytes4) public pure returns (bool) { 7 | assembly { 8 | mstore(0, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) 9 | return(0, 32) 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /contracts/mocks/ERC165/ERC165MissingData.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | contract ERC165MissingData { 6 | function supportsInterface(bytes4 interfaceId) public view {} // missing return 7 | } 8 | -------------------------------------------------------------------------------- /contracts/mocks/ERC165/ERC165NotSupported.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | contract ERC165NotSupported {} 6 | -------------------------------------------------------------------------------- /contracts/mocks/ERC165/ERC165ReturnBomb.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {IERC165} from "../../utils/introspection/IERC165.sol"; 6 | 7 | contract ERC165ReturnBombMock is IERC165 { 8 | function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { 9 | if (interfaceId == type(IERC165).interfaceId) { 10 | assembly { 11 | mstore(0, 1) 12 | } 13 | } 14 | assembly { 15 | return(0, 101500) 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /contracts/mocks/ERC2771ContextMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ContextMock} from "./ContextMock.sol"; 6 | import {Context} from "../utils/Context.sol"; 7 | import {Multicall} from "../utils/Multicall.sol"; 8 | import {ERC2771Context} from "../metatx/ERC2771Context.sol"; 9 | 10 | // By inheriting from ERC2771Context, Context's internal functions are overridden automatically 11 | contract ERC2771ContextMock is ContextMock, ERC2771Context, Multicall { 12 | /// @custom:oz-upgrades-unsafe-allow constructor 13 | constructor(address trustedForwarder) ERC2771Context(trustedForwarder) { 14 | emit Sender(_msgSender()); // _msgSender() should be accessible during construction 15 | } 16 | 17 | function _msgSender() internal view override(Context, ERC2771Context) returns (address) { 18 | return ERC2771Context._msgSender(); 19 | } 20 | 21 | function _msgData() internal view override(Context, ERC2771Context) returns (bytes calldata) { 22 | return ERC2771Context._msgData(); 23 | } 24 | 25 | function _contextSuffixLength() internal view override(Context, ERC2771Context) returns (uint256) { 26 | return ERC2771Context._contextSuffixLength(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /contracts/mocks/EtherReceiverMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | contract EtherReceiverMock { 6 | bool private _acceptEther; 7 | 8 | function setAcceptEther(bool acceptEther) public { 9 | _acceptEther = acceptEther; 10 | } 11 | 12 | receive() external payable { 13 | if (!_acceptEther) { 14 | revert(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /contracts/mocks/MulticallHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC20MulticallMock} from "./token/ERC20MulticallMock.sol"; 6 | 7 | contract MulticallHelper { 8 | function checkReturnValues( 9 | ERC20MulticallMock multicallToken, 10 | address[] calldata recipients, 11 | uint256[] calldata amounts 12 | ) external { 13 | bytes[] memory calls = new bytes[](recipients.length); 14 | for (uint256 i = 0; i < recipients.length; i++) { 15 | calls[i] = abi.encodeCall(multicallToken.transfer, (recipients[i], amounts[i])); 16 | } 17 | 18 | bytes[] memory results = multicallToken.multicall(calls); 19 | for (uint256 i = 0; i < results.length; i++) { 20 | require(abi.decode(results[i], (bool))); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /contracts/mocks/PausableMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {Pausable} from "../utils/Pausable.sol"; 6 | 7 | contract PausableMock is Pausable { 8 | bool public drasticMeasureTaken; 9 | uint256 public count; 10 | 11 | constructor() { 12 | drasticMeasureTaken = false; 13 | count = 0; 14 | } 15 | 16 | function normalProcess() external whenNotPaused { 17 | count++; 18 | } 19 | 20 | function drasticMeasure() external whenPaused { 21 | drasticMeasureTaken = true; 22 | } 23 | 24 | function pause() external { 25 | _pause(); 26 | } 27 | 28 | function unpause() external { 29 | _unpause(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /contracts/mocks/ReentrancyAttack.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {Context} from "../utils/Context.sol"; 6 | 7 | contract ReentrancyAttack is Context { 8 | function callSender(bytes calldata data) public { 9 | (bool success, ) = _msgSender().call(data); 10 | require(success, "ReentrancyAttack: failed call"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /contracts/mocks/TimelockReentrant.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {Address} from "../utils/Address.sol"; 5 | 6 | contract TimelockReentrant { 7 | address private _reenterTarget; 8 | bytes private _reenterData; 9 | bool _reentered; 10 | 11 | function disableReentrancy() external { 12 | _reentered = true; 13 | } 14 | 15 | function enableRentrancy(address target, bytes calldata data) external { 16 | _reenterTarget = target; 17 | _reenterData = data; 18 | } 19 | 20 | function reenter() external { 21 | if (!_reentered) { 22 | _reentered = true; 23 | Address.functionCall(_reenterTarget, _reenterData); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /contracts/mocks/UpgradeableBeaconMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {IBeacon} from "../proxy/beacon/IBeacon.sol"; 5 | 6 | contract UpgradeableBeaconMock is IBeacon { 7 | address public implementation; 8 | 9 | constructor(address impl) { 10 | implementation = impl; 11 | } 12 | } 13 | 14 | interface IProxyExposed { 15 | // solhint-disable-next-line func-name-mixedcase 16 | function $getBeacon() external view returns (address); 17 | } 18 | 19 | contract UpgradeableBeaconReentrantMock is IBeacon { 20 | error BeaconProxyBeaconSlotAddress(address beacon); 21 | 22 | function implementation() external view override returns (address) { 23 | // Revert with the beacon seen in the proxy at the moment of calling to check if it's 24 | // set before the call. 25 | revert BeaconProxyBeaconSlotAddress(IProxyExposed(msg.sender).$getBeacon()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /contracts/mocks/account/utils/ERC7579UtilsMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {CallType, ExecType, ModeSelector, ModePayload} from "../../../account/utils/draft-ERC7579Utils.sol"; 6 | 7 | contract ERC7579UtilsGlobalMock { 8 | function eqCallTypeGlobal(CallType callType1, CallType callType2) internal pure returns (bool) { 9 | return callType1 == callType2; 10 | } 11 | 12 | function eqExecTypeGlobal(ExecType execType1, ExecType execType2) internal pure returns (bool) { 13 | return execType1 == execType2; 14 | } 15 | 16 | function eqModeSelectorGlobal(ModeSelector modeSelector1, ModeSelector modeSelector2) internal pure returns (bool) { 17 | return modeSelector1 == modeSelector2; 18 | } 19 | 20 | function eqModePayloadGlobal(ModePayload modePayload1, ModePayload modePayload2) internal pure returns (bool) { 21 | return modePayload1 == modePayload2; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /contracts/mocks/docs/ERC20WithAutoMinerReward.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC20} from "../../token/ERC20/ERC20.sol"; 6 | 7 | contract ERC20WithAutoMinerReward is ERC20 { 8 | constructor() ERC20("Reward", "RWD") { 9 | _mintMinerReward(); 10 | } 11 | 12 | function _mintMinerReward() internal { 13 | _mint(block.coinbase, 1000); 14 | } 15 | 16 | function _update(address from, address to, uint256 value) internal virtual override { 17 | if (!(from == address(0) && to == block.coinbase)) { 18 | _mintMinerReward(); 19 | } 20 | super._update(from, to, value); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /contracts/mocks/docs/MyNFT.sol: -------------------------------------------------------------------------------- 1 | // contracts/MyNFT.sol 2 | // SPDX-License-Identifier: MIT 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC721} from "../../token/ERC721/ERC721.sol"; 6 | 7 | contract MyNFT is ERC721 { 8 | constructor() ERC721("MyNFT", "MNFT") {} 9 | } 10 | -------------------------------------------------------------------------------- /contracts/mocks/docs/access-control/AccessControlERC20MintBase.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {AccessControl} from "../../../access/AccessControl.sol"; 5 | import {ERC20} from "../../../token/ERC20/ERC20.sol"; 6 | 7 | contract AccessControlERC20MintBase is ERC20, AccessControl { 8 | // Create a new role identifier for the minter role 9 | bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); 10 | 11 | error CallerNotMinter(address caller); 12 | 13 | constructor(address minter) ERC20("MyToken", "TKN") { 14 | // Grant the minter role to a specified account 15 | _grantRole(MINTER_ROLE, minter); 16 | } 17 | 18 | function mint(address to, uint256 amount) public { 19 | // Check that the calling account has the minter role 20 | if (!hasRole(MINTER_ROLE, msg.sender)) { 21 | revert CallerNotMinter(msg.sender); 22 | } 23 | _mint(to, amount); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /contracts/mocks/docs/access-control/AccessControlERC20MintMissing.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {AccessControl} from "../../../access/AccessControl.sol"; 5 | import {ERC20} from "../../../token/ERC20/ERC20.sol"; 6 | 7 | contract AccessControlERC20MintMissing is ERC20, AccessControl { 8 | bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); 9 | bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE"); 10 | 11 | constructor() ERC20("MyToken", "TKN") { 12 | // Grant the contract deployer the default admin role: it will be able 13 | // to grant and revoke any roles 14 | _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); 15 | } 16 | 17 | function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) { 18 | _mint(to, amount); 19 | } 20 | 21 | function burn(address from, uint256 amount) public onlyRole(BURNER_ROLE) { 22 | _burn(from, amount); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /contracts/mocks/docs/access-control/AccessControlERC20MintOnlyRole.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {AccessControl} from "../../../access/AccessControl.sol"; 5 | import {ERC20} from "../../../token/ERC20/ERC20.sol"; 6 | 7 | contract AccessControlERC20Mint is ERC20, AccessControl { 8 | bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); 9 | bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE"); 10 | 11 | constructor(address minter, address burner) ERC20("MyToken", "TKN") { 12 | _grantRole(MINTER_ROLE, minter); 13 | _grantRole(BURNER_ROLE, burner); 14 | } 15 | 16 | function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) { 17 | _mint(to, amount); 18 | } 19 | 20 | function burn(address from, uint256 amount) public onlyRole(BURNER_ROLE) { 21 | _burn(from, amount); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /contracts/mocks/docs/access-control/AccessControlModified.sol: -------------------------------------------------------------------------------- 1 | // contracts/AccessControlModified.sol 2 | // SPDX-License-Identifier: MIT 3 | pragma solidity ^0.8.20; 4 | 5 | import {AccessControl} from "../../../access/AccessControl.sol"; 6 | 7 | contract AccessControlModified is AccessControl { 8 | error AccessControlNonRevocable(); 9 | 10 | // Override the revokeRole function 11 | function revokeRole(bytes32, address) public pure override { 12 | revert AccessControlNonRevocable(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /contracts/mocks/docs/access-control/AccessManagedERC20MintBase.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {AccessManaged} from "../../../access/manager/AccessManaged.sol"; 5 | import {ERC20} from "../../../token/ERC20/ERC20.sol"; 6 | 7 | contract AccessManagedERC20Mint is ERC20, AccessManaged { 8 | constructor(address manager) ERC20("MyToken", "TKN") AccessManaged(manager) {} 9 | 10 | // Minting is restricted according to the manager rules for this function. 11 | // The function is identified by its selector: 0x40c10f19. 12 | // Calculated with bytes4(keccak256('mint(address,uint256)')) 13 | function mint(address to, uint256 amount) public restricted { 14 | _mint(to, amount); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /contracts/mocks/docs/access-control/MyContractOwnable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {Ownable} from "../../../access/Ownable.sol"; 6 | 7 | contract MyContract is Ownable { 8 | constructor(address initialOwner) Ownable(initialOwner) {} 9 | 10 | function normalThing() public { 11 | // anyone can call this normalThing() 12 | } 13 | 14 | function specialThing() public onlyOwner { 15 | // only the owner can call specialThing()! 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /contracts/mocks/docs/governance/MyToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {ERC20} from "../../../token/ERC20/ERC20.sol"; 5 | import {ERC20Permit} from "../../../token/ERC20/extensions/ERC20Permit.sol"; 6 | import {ERC20Votes} from "../../../token/ERC20/extensions/ERC20Votes.sol"; 7 | import {Nonces} from "../../../utils/Nonces.sol"; 8 | 9 | contract MyToken is ERC20, ERC20Permit, ERC20Votes { 10 | constructor() ERC20("MyToken", "MTK") ERC20Permit("MyToken") {} 11 | 12 | // The functions below are overrides required by Solidity. 13 | 14 | function _update(address from, address to, uint256 amount) internal override(ERC20, ERC20Votes) { 15 | super._update(from, to, amount); 16 | } 17 | 18 | function nonces(address owner) public view virtual override(ERC20Permit, Nonces) returns (uint256) { 19 | return super.nonces(owner); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /contracts/mocks/docs/governance/MyTokenTimestampBased.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {ERC20} from "../../../token/ERC20/ERC20.sol"; 5 | import {ERC20Permit} from "../../../token/ERC20/extensions/ERC20Permit.sol"; 6 | import {ERC20Votes} from "../../../token/ERC20/extensions/ERC20Votes.sol"; 7 | import {Nonces} from "../../../utils/Nonces.sol"; 8 | 9 | contract MyTokenTimestampBased is ERC20, ERC20Permit, ERC20Votes { 10 | constructor() ERC20("MyTokenTimestampBased", "MTK") ERC20Permit("MyTokenTimestampBased") {} 11 | 12 | // Overrides IERC6372 functions to make the token & governor timestamp-based 13 | 14 | function clock() public view override returns (uint48) { 15 | return uint48(block.timestamp); 16 | } 17 | 18 | // solhint-disable-next-line func-name-mixedcase 19 | function CLOCK_MODE() public pure override returns (string memory) { 20 | return "mode=timestamp"; 21 | } 22 | 23 | // The functions below are overrides required by Solidity. 24 | 25 | function _update(address from, address to, uint256 amount) internal override(ERC20, ERC20Votes) { 26 | super._update(from, to, amount); 27 | } 28 | 29 | function nonces(address owner) public view virtual override(ERC20Permit, Nonces) returns (uint256) { 30 | return super.nonces(owner); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /contracts/mocks/docs/governance/MyTokenWrapped.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {IERC20, ERC20} from "../../../token/ERC20/ERC20.sol"; 5 | import {ERC20Permit} from "../../../token/ERC20/extensions/ERC20Permit.sol"; 6 | import {ERC20Votes} from "../../../token/ERC20/extensions/ERC20Votes.sol"; 7 | import {ERC20Wrapper} from "../../../token/ERC20/extensions/ERC20Wrapper.sol"; 8 | import {Nonces} from "../../../utils/Nonces.sol"; 9 | 10 | contract MyTokenWrapped is ERC20, ERC20Permit, ERC20Votes, ERC20Wrapper { 11 | constructor( 12 | IERC20 wrappedToken 13 | ) ERC20("MyTokenWrapped", "MTK") ERC20Permit("MyTokenWrapped") ERC20Wrapper(wrappedToken) {} 14 | 15 | // The functions below are overrides required by Solidity. 16 | 17 | function decimals() public view override(ERC20, ERC20Wrapper) returns (uint8) { 18 | return super.decimals(); 19 | } 20 | 21 | function _update(address from, address to, uint256 amount) internal override(ERC20, ERC20Votes) { 22 | super._update(from, to, amount); 23 | } 24 | 25 | function nonces(address owner) public view virtual override(ERC20Permit, Nonces) returns (uint256) { 26 | return super.nonces(owner); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /contracts/mocks/docs/token/ERC1155/GameItems.sol: -------------------------------------------------------------------------------- 1 | // contracts/GameItems.sol 2 | // SPDX-License-Identifier: MIT 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC1155} from "../../../../token/ERC1155/ERC1155.sol"; 6 | 7 | contract GameItems is ERC1155 { 8 | uint256 public constant GOLD = 0; 9 | uint256 public constant SILVER = 1; 10 | uint256 public constant THORS_HAMMER = 2; 11 | uint256 public constant SWORD = 3; 12 | uint256 public constant SHIELD = 4; 13 | 14 | constructor() ERC1155("https://game.example/api/item/{id}.json") { 15 | _mint(msg.sender, GOLD, 10 ** 18, ""); 16 | _mint(msg.sender, SILVER, 10 ** 27, ""); 17 | _mint(msg.sender, THORS_HAMMER, 1, ""); 18 | _mint(msg.sender, SWORD, 10 ** 9, ""); 19 | _mint(msg.sender, SHIELD, 10 ** 9, ""); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /contracts/mocks/docs/token/ERC1155/MyERC115HolderContract.sol: -------------------------------------------------------------------------------- 1 | // contracts/MyERC115HolderContract.sol 2 | // SPDX-License-Identifier: MIT 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC1155Holder} from "../../../../token/ERC1155/utils/ERC1155Holder.sol"; 6 | 7 | contract MyERC115HolderContract is ERC1155Holder {} 8 | -------------------------------------------------------------------------------- /contracts/mocks/docs/token/ERC20/GLDToken.sol: -------------------------------------------------------------------------------- 1 | // contracts/GLDToken.sol 2 | // SPDX-License-Identifier: MIT 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC20} from "../../../../token/ERC20/ERC20.sol"; 6 | 7 | contract GLDToken is ERC20 { 8 | constructor(uint256 initialSupply) ERC20("Gold", "GLD") { 9 | _mint(msg.sender, initialSupply); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /contracts/mocks/docs/token/ERC6909/ERC6909GameItems.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {ERC6909Metadata} from "../../../../token/ERC6909/extensions/draft-ERC6909Metadata.sol"; 5 | 6 | contract ERC6909GameItems is ERC6909Metadata { 7 | uint256 public constant GOLD = 0; 8 | uint256 public constant SILVER = 1; 9 | uint256 public constant THORS_HAMMER = 2; 10 | uint256 public constant SWORD = 3; 11 | uint256 public constant SHIELD = 4; 12 | 13 | constructor() { 14 | _setDecimals(GOLD, 18); 15 | _setDecimals(SILVER, 18); 16 | // Default decimals is 0 17 | _setDecimals(SWORD, 9); 18 | _setDecimals(SHIELD, 9); 19 | 20 | _mint(msg.sender, GOLD, 10 ** 18); 21 | _mint(msg.sender, SILVER, 10_000 ** 18); 22 | _mint(msg.sender, THORS_HAMMER, 1); 23 | _mint(msg.sender, SWORD, 10 ** 9); 24 | _mint(msg.sender, SHIELD, 10 ** 9); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /contracts/mocks/docs/token/ERC721/GameItem.sol: -------------------------------------------------------------------------------- 1 | // contracts/GameItem.sol 2 | // SPDX-License-Identifier: MIT 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC721URIStorage, ERC721} from "../../../../token/ERC721/extensions/ERC721URIStorage.sol"; 6 | 7 | contract GameItem is ERC721URIStorage { 8 | uint256 private _nextTokenId; 9 | 10 | constructor() ERC721("GameItem", "ITM") {} 11 | 12 | function awardItem(address player, string memory tokenURI) public returns (uint256) { 13 | uint256 tokenId = _nextTokenId++; 14 | _mint(player, tokenId); 15 | _setTokenURI(tokenId, tokenURI); 16 | 17 | return tokenId; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/mocks/docs/utilities/Base64NFT.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC721} from "../../../token/ERC721/ERC721.sol"; 6 | import {Strings} from "../../../utils/Strings.sol"; 7 | import {Base64} from "../../../utils/Base64.sol"; 8 | 9 | contract Base64NFT is ERC721 { 10 | using Strings for uint256; 11 | 12 | constructor() ERC721("Base64NFT", "MTK") {} 13 | 14 | // ... 15 | 16 | function tokenURI(uint256 tokenId) public pure override returns (string memory) { 17 | // Equivalent to: 18 | // { 19 | // "name": "Base64NFT #1", 20 | // // Replace with extra ERC-721 Metadata properties 21 | // } 22 | // prettier-ignore 23 | string memory dataURI = string.concat("{\"name\": \"Base64NFT #", tokenId.toString(), "\"}"); 24 | 25 | return string.concat("data:application/json;base64,", Base64.encode(bytes(dataURI))); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /contracts/mocks/docs/utilities/Multicall.sol: -------------------------------------------------------------------------------- 1 | // contracts/Box.sol 2 | // SPDX-License-Identifier: MIT 3 | pragma solidity ^0.8.20; 4 | 5 | import {Multicall} from "../../../utils/Multicall.sol"; 6 | 7 | contract Box is Multicall { 8 | function foo() public { 9 | // ... 10 | } 11 | 12 | function bar() public { 13 | // ... 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /contracts/mocks/governance/GovernorCountingOverridableMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.24; 4 | 5 | import {Governor} from "../../governance/Governor.sol"; 6 | import {GovernorSettings} from "../../governance/extensions/GovernorSettings.sol"; 7 | import {GovernorVotesQuorumFraction} from "../../governance/extensions/GovernorVotesQuorumFraction.sol"; 8 | import {GovernorCountingOverridable} from "../../governance/extensions/GovernorCountingOverridable.sol"; 9 | 10 | abstract contract GovernorCountingOverridableMock is 11 | GovernorSettings, 12 | GovernorVotesQuorumFraction, 13 | GovernorCountingOverridable 14 | { 15 | function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) { 16 | return super.proposalThreshold(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /contracts/mocks/governance/GovernorFractionalMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.24; 4 | 5 | import {Governor} from "../../governance/Governor.sol"; 6 | import {GovernorSettings} from "../../governance/extensions/GovernorSettings.sol"; 7 | import {GovernorCountingFractional} from "../../governance/extensions/GovernorCountingFractional.sol"; 8 | import {GovernorVotesQuorumFraction} from "../../governance/extensions/GovernorVotesQuorumFraction.sol"; 9 | 10 | abstract contract GovernorFractionalMock is GovernorSettings, GovernorVotesQuorumFraction, GovernorCountingFractional { 11 | function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) { 12 | return super.proposalThreshold(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /contracts/mocks/governance/GovernorMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.24; 4 | 5 | import {Governor} from "../../governance/Governor.sol"; 6 | import {GovernorSettings} from "../../governance/extensions/GovernorSettings.sol"; 7 | import {GovernorCountingSimple} from "../../governance/extensions/GovernorCountingSimple.sol"; 8 | import {GovernorVotesQuorumFraction} from "../../governance/extensions/GovernorVotesQuorumFraction.sol"; 9 | 10 | abstract contract GovernorMock is GovernorSettings, GovernorVotesQuorumFraction, GovernorCountingSimple { 11 | function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) { 12 | return super.proposalThreshold(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /contracts/mocks/governance/GovernorProposalGuardianMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.24; 4 | 5 | import {Governor} from "../../governance/Governor.sol"; 6 | import {GovernorSettings} from "../../governance/extensions/GovernorSettings.sol"; 7 | import {GovernorCountingSimple} from "../../governance/extensions/GovernorCountingSimple.sol"; 8 | import {GovernorVotesQuorumFraction} from "../../governance/extensions/GovernorVotesQuorumFraction.sol"; 9 | import {GovernorProposalGuardian} from "../../governance/extensions/GovernorProposalGuardian.sol"; 10 | 11 | abstract contract GovernorProposalGuardianMock is 12 | GovernorSettings, 13 | GovernorVotesQuorumFraction, 14 | GovernorCountingSimple, 15 | GovernorProposalGuardian 16 | { 17 | function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) { 18 | return super.proposalThreshold(); 19 | } 20 | 21 | function _validateCancel( 22 | uint256 proposalId, 23 | address caller 24 | ) internal view override(Governor, GovernorProposalGuardian) returns (bool) { 25 | return super._validateCancel(proposalId, caller); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /contracts/mocks/governance/GovernorVoteMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.24; 4 | 5 | import {GovernorCountingSimple} from "../../governance/extensions/GovernorCountingSimple.sol"; 6 | import {GovernorVotes} from "../../governance/extensions/GovernorVotes.sol"; 7 | 8 | abstract contract GovernorVoteMocks is GovernorVotes, GovernorCountingSimple { 9 | function quorum(uint256) public pure override returns (uint256) { 10 | return 0; 11 | } 12 | 13 | function votingDelay() public pure override returns (uint256) { 14 | return 4; 15 | } 16 | 17 | function votingPeriod() public pure override returns (uint256) { 18 | return 16; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /contracts/mocks/proxy/BadBeacon.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | contract BadBeaconNoImpl {} 6 | 7 | contract BadBeaconNotContract { 8 | function implementation() external pure returns (address) { 9 | return address(0x1); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /contracts/mocks/proxy/ClashingImplementation.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | /** 6 | * @dev Implementation contract with a payable changeAdmin(address) function made to clash with 7 | * TransparentUpgradeableProxy's to test correct functioning of the Transparent Proxy feature. 8 | */ 9 | contract ClashingImplementation { 10 | event ClashingImplementationCall(); 11 | 12 | function upgradeToAndCall(address, bytes calldata) external payable { 13 | emit ClashingImplementationCall(); 14 | } 15 | 16 | function delegatedFunction() external pure returns (bool) { 17 | return true; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/mocks/proxy/UUPSUpgradeableMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.22; 4 | 5 | import {UUPSUpgradeable} from "../../proxy/utils/UUPSUpgradeable.sol"; 6 | import {ERC1967Utils} from "../../proxy/ERC1967/ERC1967Utils.sol"; 7 | 8 | contract NonUpgradeableMock { 9 | uint256 internal _counter; 10 | 11 | function current() external view returns (uint256) { 12 | return _counter; 13 | } 14 | 15 | function increment() external { 16 | ++_counter; 17 | } 18 | } 19 | 20 | contract UUPSUpgradeableMock is NonUpgradeableMock, UUPSUpgradeable { 21 | // Not having any checks in this function is dangerous! Do not do this outside tests! 22 | function _authorizeUpgrade(address) internal override {} 23 | } 24 | 25 | contract UUPSUpgradeableUnsafeMock is UUPSUpgradeableMock { 26 | function upgradeToAndCall(address newImplementation, bytes memory data) public payable override { 27 | ERC1967Utils.upgradeToAndCall(newImplementation, data); 28 | } 29 | } 30 | 31 | contract UUPSUnsupportedProxiableUUID is UUPSUpgradeableMock { 32 | function proxiableUUID() external pure override returns (bytes32) { 33 | return keccak256("invalid UUID"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC1363ForceApproveMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC1363} from "../../token/ERC20/extensions/ERC1363.sol"; 6 | 7 | // contract that replicate USDT approval behavior in approveAndCall 8 | abstract contract ERC1363ForceApproveMock is ERC1363 { 9 | function approveAndCall(address spender, uint256 amount, bytes memory data) public virtual override returns (bool) { 10 | require(amount == 0 || allowance(msg.sender, spender) == 0, "USDT approval failure"); 11 | return super.approveAndCall(spender, amount, data); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC1363NoReturnMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC1363} from "../../token/ERC20/extensions/ERC1363.sol"; 6 | 7 | abstract contract ERC1363NoReturnMock is ERC1363 { 8 | function transferAndCall(address to, uint256 value, bytes memory data) public override returns (bool) { 9 | super.transferAndCall(to, value, data); 10 | assembly { 11 | return(0, 0) 12 | } 13 | } 14 | 15 | function transferFromAndCall( 16 | address from, 17 | address to, 18 | uint256 value, 19 | bytes memory data 20 | ) public override returns (bool) { 21 | super.transferFromAndCall(from, to, value, data); 22 | assembly { 23 | return(0, 0) 24 | } 25 | } 26 | 27 | function approveAndCall(address spender, uint256 value, bytes memory data) public override returns (bool) { 28 | super.approveAndCall(spender, value, data); 29 | assembly { 30 | return(0, 0) 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC1363ReturnFalseMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {IERC20, ERC20} from "../../token/ERC20/ERC20.sol"; 6 | import {ERC1363} from "../../token/ERC20/extensions/ERC1363.sol"; 7 | 8 | abstract contract ERC1363ReturnFalseOnERC20Mock is ERC1363 { 9 | function transfer(address, uint256) public pure override(IERC20, ERC20) returns (bool) { 10 | return false; 11 | } 12 | 13 | function transferFrom(address, address, uint256) public pure override(IERC20, ERC20) returns (bool) { 14 | return false; 15 | } 16 | 17 | function approve(address, uint256) public pure override(IERC20, ERC20) returns (bool) { 18 | return false; 19 | } 20 | } 21 | 22 | abstract contract ERC1363ReturnFalseMock is ERC1363 { 23 | function transferAndCall(address, uint256, bytes memory) public pure override returns (bool) { 24 | return false; 25 | } 26 | 27 | function transferFromAndCall(address, address, uint256, bytes memory) public pure override returns (bool) { 28 | return false; 29 | } 30 | 31 | function approveAndCall(address, uint256, bytes memory) public pure override returns (bool) { 32 | return false; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC20ApprovalMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {ERC20} from "../../token/ERC20/ERC20.sol"; 5 | 6 | abstract contract ERC20ApprovalMock is ERC20 { 7 | function _approve(address owner, address spender, uint256 amount, bool) internal virtual override { 8 | super._approve(owner, spender, amount, true); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC20BridgeableMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC20, ERC20Bridgeable} from "../../token/ERC20/extensions/draft-ERC20Bridgeable.sol"; 6 | 7 | abstract contract ERC20BridgeableMock is ERC20Bridgeable { 8 | address private _bridge; 9 | 10 | error OnlyTokenBridge(); 11 | event OnlyTokenBridgeFnCalled(address caller); 12 | 13 | constructor(address bridge) { 14 | _bridge = bridge; 15 | } 16 | 17 | function onlyTokenBridgeFn() external onlyTokenBridge { 18 | emit OnlyTokenBridgeFnCalled(msg.sender); 19 | } 20 | 21 | function _checkTokenBridge(address sender) internal view override { 22 | if (sender != _bridge) { 23 | revert OnlyTokenBridge(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC20DecimalsMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC20} from "../../token/ERC20/ERC20.sol"; 6 | 7 | abstract contract ERC20DecimalsMock is ERC20 { 8 | uint8 private immutable _decimals; 9 | 10 | constructor(uint8 decimals_) { 11 | _decimals = decimals_; 12 | } 13 | 14 | function decimals() public view override returns (uint8) { 15 | return _decimals; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC20ExcessDecimalsMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | contract ERC20ExcessDecimalsMock { 6 | function decimals() public pure returns (uint256) { 7 | return type(uint256).max; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC20FlashMintMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC20FlashMint} from "../../token/ERC20/extensions/ERC20FlashMint.sol"; 6 | 7 | abstract contract ERC20FlashMintMock is ERC20FlashMint { 8 | uint256 _flashFeeAmount; 9 | address _flashFeeReceiverAddress; 10 | 11 | function setFlashFee(uint256 amount) public { 12 | _flashFeeAmount = amount; 13 | } 14 | 15 | function _flashFee(address, uint256) internal view override returns (uint256) { 16 | return _flashFeeAmount; 17 | } 18 | 19 | function setFlashFeeReceiver(address receiver) public { 20 | _flashFeeReceiverAddress = receiver; 21 | } 22 | 23 | function _flashFeeReceiver() internal view override returns (address) { 24 | return _flashFeeReceiverAddress; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC20ForceApproveMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC20} from "../../token/ERC20/ERC20.sol"; 6 | 7 | // contract that replicates USDT (0xdac17f958d2ee523a2206206994597c13d831ec7) approval behavior 8 | abstract contract ERC20ForceApproveMock is ERC20 { 9 | function approve(address spender, uint256 amount) public virtual override returns (bool) { 10 | require(amount == 0 || allowance(msg.sender, spender) == 0, "USDT approval failure"); 11 | return super.approve(spender, amount); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC20Mock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {ERC20} from "../../token/ERC20/ERC20.sol"; 5 | 6 | contract ERC20Mock is ERC20 { 7 | constructor() ERC20("ERC20Mock", "E20M") {} 8 | 9 | function mint(address account, uint256 amount) external { 10 | _mint(account, amount); 11 | } 12 | 13 | function burn(address account, uint256 amount) external { 14 | _burn(account, amount); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC20MulticallMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC20} from "../../token/ERC20/ERC20.sol"; 6 | import {Multicall} from "../../utils/Multicall.sol"; 7 | 8 | abstract contract ERC20MulticallMock is ERC20, Multicall {} 9 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC20NoReturnMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC20} from "../../token/ERC20/ERC20.sol"; 6 | 7 | abstract contract ERC20NoReturnMock is ERC20 { 8 | function transfer(address to, uint256 amount) public override returns (bool) { 9 | super.transfer(to, amount); 10 | assembly { 11 | return(0, 0) 12 | } 13 | } 14 | 15 | function transferFrom(address from, address to, uint256 amount) public override returns (bool) { 16 | super.transferFrom(from, to, amount); 17 | assembly { 18 | return(0, 0) 19 | } 20 | } 21 | 22 | function approve(address spender, uint256 amount) public override returns (bool) { 23 | super.approve(spender, amount); 24 | assembly { 25 | return(0, 0) 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC20Reentrant.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {ERC20} from "../../token/ERC20/ERC20.sol"; 5 | import {Address} from "../../utils/Address.sol"; 6 | 7 | contract ERC20Reentrant is ERC20("TEST", "TST") { 8 | enum Type { 9 | No, 10 | Before, 11 | After 12 | } 13 | 14 | Type private _reenterType; 15 | address private _reenterTarget; 16 | bytes private _reenterData; 17 | 18 | function scheduleReenter(Type when, address target, bytes calldata data) external { 19 | _reenterType = when; 20 | _reenterTarget = target; 21 | _reenterData = data; 22 | } 23 | 24 | function functionCall(address target, bytes memory data) public returns (bytes memory) { 25 | return Address.functionCall(target, data); 26 | } 27 | 28 | function _update(address from, address to, uint256 amount) internal override { 29 | if (_reenterType == Type.Before) { 30 | _reenterType = Type.No; 31 | functionCall(_reenterTarget, _reenterData); 32 | } 33 | super._update(from, to, amount); 34 | if (_reenterType == Type.After) { 35 | _reenterType = Type.No; 36 | functionCall(_reenterTarget, _reenterData); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC20ReturnFalseMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC20} from "../../token/ERC20/ERC20.sol"; 6 | 7 | abstract contract ERC20ReturnFalseMock is ERC20 { 8 | function transfer(address, uint256) public pure override returns (bool) { 9 | return false; 10 | } 11 | 12 | function transferFrom(address, address, uint256) public pure override returns (bool) { 13 | return false; 14 | } 15 | 16 | function approve(address, uint256) public pure override returns (bool) { 17 | return false; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC20VotesAdditionalCheckpointsMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {ERC20Votes} from "../../token/ERC20/extensions/ERC20Votes.sol"; 5 | import {VotesExtended, Votes} from "../../governance/utils/VotesExtended.sol"; 6 | import {SafeCast} from "../../utils/math/SafeCast.sol"; 7 | 8 | abstract contract ERC20VotesExtendedMock is ERC20Votes, VotesExtended { 9 | function _delegate(address account, address delegatee) internal virtual override(Votes, VotesExtended) { 10 | return super._delegate(account, delegatee); 11 | } 12 | 13 | function _transferVotingUnits( 14 | address from, 15 | address to, 16 | uint256 amount 17 | ) internal virtual override(Votes, VotesExtended) { 18 | return super._transferVotingUnits(from, to, amount); 19 | } 20 | } 21 | 22 | abstract contract ERC20VotesExtendedTimestampMock is ERC20VotesExtendedMock { 23 | function clock() public view virtual override returns (uint48) { 24 | return SafeCast.toUint48(block.timestamp); 25 | } 26 | 27 | // solhint-disable-next-line func-name-mixedcase 28 | function CLOCK_MODE() public view virtual override returns (string memory) { 29 | return "mode=timestamp"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC20VotesTimestampMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC20Votes} from "../../token/ERC20/extensions/ERC20Votes.sol"; 6 | import {ERC721Votes} from "../../token/ERC721/extensions/ERC721Votes.sol"; 7 | import {SafeCast} from "../../utils/math/SafeCast.sol"; 8 | 9 | abstract contract ERC20VotesTimestampMock is ERC20Votes { 10 | function clock() public view virtual override returns (uint48) { 11 | return SafeCast.toUint48(block.timestamp); 12 | } 13 | 14 | // solhint-disable-next-line func-name-mixedcase 15 | function CLOCK_MODE() public view virtual override returns (string memory) { 16 | return "mode=timestamp"; 17 | } 18 | } 19 | 20 | abstract contract ERC721VotesTimestampMock is ERC721Votes { 21 | function clock() public view virtual override returns (uint48) { 22 | return SafeCast.toUint48(block.timestamp); 23 | } 24 | 25 | // solhint-disable-next-line func-name-mixedcase 26 | function CLOCK_MODE() public view virtual override returns (string memory) { 27 | return "mode=timestamp"; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC4626LimitsMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC4626} from "../../token/ERC20/extensions/ERC4626.sol"; 6 | 7 | abstract contract ERC4626LimitsMock is ERC4626 { 8 | uint256 _maxDeposit; 9 | uint256 _maxMint; 10 | 11 | constructor() { 12 | _maxDeposit = 100 ether; 13 | _maxMint = 100 ether; 14 | } 15 | 16 | function maxDeposit(address) public view override returns (uint256) { 17 | return _maxDeposit; 18 | } 19 | 20 | function maxMint(address) public view override returns (uint256) { 21 | return _maxMint; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC4626Mock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import {IERC20, ERC20} from "../../token/ERC20/ERC20.sol"; 5 | import {ERC4626} from "../../token/ERC20/extensions/ERC4626.sol"; 6 | 7 | contract ERC4626Mock is ERC4626 { 8 | constructor(address underlying) ERC20("ERC4626Mock", "E4626M") ERC4626(IERC20(underlying)) {} 9 | 10 | function mint(address account, uint256 amount) external { 11 | _mint(account, amount); 12 | } 13 | 14 | function burn(address account, uint256 amount) external { 15 | _burn(account, amount); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC4626OffsetMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC4626} from "../../token/ERC20/extensions/ERC4626.sol"; 6 | 7 | abstract contract ERC4626OffsetMock is ERC4626 { 8 | uint8 private immutable _offset; 9 | 10 | constructor(uint8 offset_) { 11 | _offset = offset_; 12 | } 13 | 14 | function _decimalsOffset() internal view virtual override returns (uint8) { 15 | return _offset; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /contracts/mocks/token/ERC721URIStorageMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ERC721URIStorage} from "../../token/ERC721/extensions/ERC721URIStorage.sol"; 6 | 7 | abstract contract ERC721URIStorageMock is ERC721URIStorage { 8 | string private _baseTokenURI; 9 | 10 | function _baseURI() internal view virtual override returns (string memory) { 11 | return _baseTokenURI; 12 | } 13 | 14 | function setBaseURI(string calldata newBaseTokenURI) public { 15 | _baseTokenURI = newBaseTokenURI; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /contracts/mocks/utils/cryptography/ERC7739Mock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {ECDSA} from "../../../utils/cryptography/ECDSA.sol"; 6 | import {EIP712} from "../../../utils/cryptography/EIP712.sol"; 7 | import {ERC7739} from "../../../utils/cryptography/signers/draft-ERC7739.sol"; 8 | import {SignerECDSA} from "../../../utils/cryptography/signers/SignerECDSA.sol"; 9 | import {SignerP256} from "../../../utils/cryptography/signers/SignerP256.sol"; 10 | import {SignerRSA} from "../../../utils/cryptography/signers/SignerRSA.sol"; 11 | 12 | contract ERC7739ECDSAMock is ERC7739, SignerECDSA { 13 | constructor(address signerAddr) EIP712("ERC7739ECDSA", "1") { 14 | _setSigner(signerAddr); 15 | } 16 | } 17 | 18 | contract ERC7739P256Mock is ERC7739, SignerP256 { 19 | constructor(bytes32 qx, bytes32 qy) EIP712("ERC7739P256", "1") { 20 | _setSigner(qx, qy); 21 | } 22 | } 23 | 24 | contract ERC7739RSAMock is ERC7739, SignerRSA { 25 | constructor(bytes memory e, bytes memory n) EIP712("ERC7739RSA", "1") { 26 | _setSigner(e, n); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /contracts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openzeppelin/contracts", 3 | "description": "Secure Smart Contract library for Solidity", 4 | "version": "5.3.0", 5 | "files": [ 6 | "**/*.sol", 7 | "/build/contracts/*.json", 8 | "!/mocks/**/*" 9 | ], 10 | "scripts": { 11 | "prepack": "bash ../scripts/prepack.sh", 12 | "prepare-docs": "cd ..; npm run prepare-docs" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/OpenZeppelin/openzeppelin-contracts.git" 17 | }, 18 | "keywords": [ 19 | "solidity", 20 | "ethereum", 21 | "smart", 22 | "contracts", 23 | "security", 24 | "zeppelin" 25 | ], 26 | "author": "OpenZeppelin Community ", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/OpenZeppelin/openzeppelin-contracts/issues" 30 | }, 31 | "homepage": "https://openzeppelin.com/contracts/" 32 | } 33 | -------------------------------------------------------------------------------- /contracts/proxy/beacon/IBeacon.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol) 3 | 4 | pragma solidity >=0.4.16; 5 | 6 | /** 7 | * @dev This is the interface that {BeaconProxy} expects of its beacon. 8 | */ 9 | interface IBeacon { 10 | /** 11 | * @dev Must return an address that can be used as a delegate call target. 12 | * 13 | * {UpgradeableBeacon} will check that this address is a contract. 14 | */ 15 | function implementation() external view returns (address); 16 | } 17 | -------------------------------------------------------------------------------- /contracts/token/ERC1155/extensions/ERC1155Burnable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/extensions/ERC1155Burnable.sol) 3 | 4 | pragma solidity ^0.8.20; 5 | 6 | import {ERC1155} from "../ERC1155.sol"; 7 | 8 | /** 9 | * @dev Extension of {ERC1155} that allows token holders to destroy both their 10 | * own tokens and those that they have been approved to use. 11 | */ 12 | abstract contract ERC1155Burnable is ERC1155 { 13 | function burn(address account, uint256 id, uint256 value) public virtual { 14 | if (account != _msgSender() && !isApprovedForAll(account, _msgSender())) { 15 | revert ERC1155MissingApprovalForAll(_msgSender(), account); 16 | } 17 | 18 | _burn(account, id, value); 19 | } 20 | 21 | function burnBatch(address account, uint256[] memory ids, uint256[] memory values) public virtual { 22 | if (account != _msgSender() && !isApprovedForAll(account, _msgSender())) { 23 | revert ERC1155MissingApprovalForAll(_msgSender(), account); 24 | } 25 | 26 | _burnBatch(account, ids, values); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/extensions/IERC1155MetadataURI.sol) 3 | 4 | pragma solidity >=0.6.2; 5 | 6 | import {IERC1155} from "../IERC1155.sol"; 7 | 8 | /** 9 | * @dev Interface of the optional ERC1155MetadataExtension interface, as defined 10 | * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[ERC]. 11 | */ 12 | interface IERC1155MetadataURI is IERC1155 { 13 | /** 14 | * @dev Returns the URI for token type `id`. 15 | * 16 | * If the `\{id\}` substring is present in the URI, it must be replaced by 17 | * clients with the actual token type ID. 18 | */ 19 | function uri(uint256 id) external view returns (string memory); 20 | } 21 | -------------------------------------------------------------------------------- /contracts/token/ERC20/extensions/ERC20Burnable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol) 3 | 4 | pragma solidity ^0.8.20; 5 | 6 | import {ERC20} from "../ERC20.sol"; 7 | import {Context} from "../../../utils/Context.sol"; 8 | 9 | /** 10 | * @dev Extension of {ERC20} that allows token holders to destroy both their own 11 | * tokens and those that they have an allowance for, in a way that can be 12 | * recognized off-chain (via event analysis). 13 | */ 14 | abstract contract ERC20Burnable is Context, ERC20 { 15 | /** 16 | * @dev Destroys a `value` amount of tokens from the caller. 17 | * 18 | * See {ERC20-_burn}. 19 | */ 20 | function burn(uint256 value) public virtual { 21 | _burn(_msgSender(), value); 22 | } 23 | 24 | /** 25 | * @dev Destroys a `value` amount of tokens from `account`, deducting from 26 | * the caller's allowance. 27 | * 28 | * See {ERC20-_burn} and {ERC20-allowance}. 29 | * 30 | * Requirements: 31 | * 32 | * - the caller must have allowance for ``accounts``'s tokens of at least 33 | * `value`. 34 | */ 35 | function burnFrom(address account, uint256 value) public virtual { 36 | _spendAllowance(account, _msgSender(), value); 37 | _burn(account, value); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /contracts/token/ERC20/extensions/IERC20Metadata.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol) 3 | 4 | pragma solidity >=0.6.2; 5 | 6 | import {IERC20} from "../IERC20.sol"; 7 | 8 | /** 9 | * @dev Interface for the optional metadata functions from the ERC-20 standard. 10 | */ 11 | interface IERC20Metadata is IERC20 { 12 | /** 13 | * @dev Returns the name of the token. 14 | */ 15 | function name() external view returns (string memory); 16 | 17 | /** 18 | * @dev Returns the symbol of the token. 19 | */ 20 | function symbol() external view returns (string memory); 21 | 22 | /** 23 | * @dev Returns the decimals places of the token. 24 | */ 25 | function decimals() external view returns (uint8); 26 | } 27 | -------------------------------------------------------------------------------- /contracts/token/ERC6909/README.adoc: -------------------------------------------------------------------------------- 1 | = ERC-6909 2 | 3 | [.readme-notice] 4 | NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/token/erc6909 5 | 6 | This set of interfaces and contracts are all related to the https://eips.ethereum.org/EIPS/eip-6909[ERC-6909 Minimal Multi-Token Interface]. 7 | 8 | The ERC consists of four interfaces which fulfill different roles--the interfaces are as follows: 9 | 10 | . {IERC6909}: Base interface for a vanilla ERC6909 token. 11 | . {IERC6909ContentURI}: Extends the base interface and adds content URI (contract and token level) functionality. 12 | . {IERC6909Metadata}: Extends the base interface and adds metadata functionality, which exposes a name, symbol, and decimals for each token id. 13 | . {IERC6909TokenSupply}: Extends the base interface and adds total supply functionality for each token id. 14 | 15 | Implementations are provided for each of the 4 interfaces defined in the ERC. 16 | 17 | == Core 18 | 19 | {{ERC6909}} 20 | 21 | == Extensions 22 | 23 | {{ERC6909ContentURI}} 24 | 25 | {{ERC6909Metadata}} 26 | 27 | {{ERC6909TokenSupply}} 28 | -------------------------------------------------------------------------------- /contracts/token/ERC721/IERC721Receiver.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol) 3 | 4 | pragma solidity >=0.5.0; 5 | 6 | /** 7 | * @title ERC-721 token receiver interface 8 | * @dev Interface for any contract that wants to support safeTransfers 9 | * from ERC-721 asset contracts. 10 | */ 11 | interface IERC721Receiver { 12 | /** 13 | * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} 14 | * by `operator` from `from`, this function is called. 15 | * 16 | * It must return its Solidity selector to confirm the token transfer. 17 | * If any other value is returned or the interface is not implemented by the recipient, the transfer will be 18 | * reverted. 19 | * 20 | * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. 21 | */ 22 | function onERC721Received( 23 | address operator, 24 | address from, 25 | uint256 tokenId, 26 | bytes calldata data 27 | ) external returns (bytes4); 28 | } 29 | -------------------------------------------------------------------------------- /contracts/token/ERC721/extensions/ERC721Burnable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/extensions/ERC721Burnable.sol) 3 | 4 | pragma solidity ^0.8.20; 5 | 6 | import {ERC721} from "../ERC721.sol"; 7 | import {Context} from "../../../utils/Context.sol"; 8 | 9 | /** 10 | * @title ERC-721 Burnable Token 11 | * @dev ERC-721 Token that can be burned (destroyed). 12 | */ 13 | abstract contract ERC721Burnable is Context, ERC721 { 14 | /** 15 | * @dev Burns `tokenId`. See {ERC721-_burn}. 16 | * 17 | * Requirements: 18 | * 19 | * - The caller must own `tokenId` or be an approved operator. 20 | */ 21 | function burn(uint256 tokenId) public virtual { 22 | // Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists 23 | // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here. 24 | _update(address(0), tokenId, _msgSender()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /contracts/token/ERC721/extensions/ERC721Royalty.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/extensions/ERC721Royalty.sol) 3 | 4 | pragma solidity ^0.8.20; 5 | 6 | import {ERC721} from "../ERC721.sol"; 7 | import {IERC165} from "../../../utils/introspection/ERC165.sol"; 8 | import {ERC2981} from "../../common/ERC2981.sol"; 9 | 10 | /** 11 | * @dev Extension of ERC-721 with the ERC-2981 NFT Royalty Standard, a standardized way to retrieve royalty payment 12 | * information. 13 | * 14 | * Royalty information can be specified globally for all token ids via {ERC2981-_setDefaultRoyalty}, and/or individually 15 | * for specific token ids via {ERC2981-_setTokenRoyalty}. The latter takes precedence over the first. 16 | * 17 | * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See 18 | * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the ERC. Marketplaces are expected to 19 | * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported. 20 | */ 21 | abstract contract ERC721Royalty is ERC2981, ERC721 { 22 | /// @inheritdoc IERC165 23 | function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC2981) returns (bool) { 24 | return super.supportsInterface(interfaceId); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /contracts/token/ERC721/extensions/IERC721Enumerable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Enumerable.sol) 3 | 4 | pragma solidity >=0.6.2; 5 | 6 | import {IERC721} from "../IERC721.sol"; 7 | 8 | /** 9 | * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension 10 | * @dev See https://eips.ethereum.org/EIPS/eip-721 11 | */ 12 | interface IERC721Enumerable is IERC721 { 13 | /** 14 | * @dev Returns the total amount of tokens stored by the contract. 15 | */ 16 | function totalSupply() external view returns (uint256); 17 | 18 | /** 19 | * @dev Returns a token ID owned by `owner` at a given `index` of its token list. 20 | * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. 21 | */ 22 | function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); 23 | 24 | /** 25 | * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. 26 | * Use along with {totalSupply} to enumerate all tokens. 27 | */ 28 | function tokenByIndex(uint256 index) external view returns (uint256); 29 | } 30 | -------------------------------------------------------------------------------- /contracts/token/ERC721/extensions/IERC721Metadata.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol) 3 | 4 | pragma solidity >=0.6.2; 5 | 6 | import {IERC721} from "../IERC721.sol"; 7 | 8 | /** 9 | * @title ERC-721 Non-Fungible Token Standard, optional metadata extension 10 | * @dev See https://eips.ethereum.org/EIPS/eip-721 11 | */ 12 | interface IERC721Metadata is IERC721 { 13 | /** 14 | * @dev Returns the token collection name. 15 | */ 16 | function name() external view returns (string memory); 17 | 18 | /** 19 | * @dev Returns the token collection symbol. 20 | */ 21 | function symbol() external view returns (string memory); 22 | 23 | /** 24 | * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. 25 | */ 26 | function tokenURI(uint256 tokenId) external view returns (string memory); 27 | } 28 | -------------------------------------------------------------------------------- /contracts/token/ERC721/utils/ERC721Holder.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/utils/ERC721Holder.sol) 3 | 4 | pragma solidity ^0.8.20; 5 | 6 | import {IERC721Receiver} from "../IERC721Receiver.sol"; 7 | 8 | /** 9 | * @dev Implementation of the {IERC721Receiver} interface. 10 | * 11 | * Accepts all token transfers. 12 | * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or 13 | * {IERC721-setApprovalForAll}. 14 | */ 15 | abstract contract ERC721Holder is IERC721Receiver { 16 | /** 17 | * @dev See {IERC721Receiver-onERC721Received}. 18 | * 19 | * Always returns `IERC721Receiver.onERC721Received.selector`. 20 | */ 21 | function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) { 22 | return this.onERC721Received.selector; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /contracts/token/common/README.adoc: -------------------------------------------------------------------------------- 1 | = Common (Tokens) 2 | 3 | Functionality that is common to multiple token standards. 4 | 5 | * {ERC2981}: NFT Royalties compatible with both ERC-721 and ERC-1155. 6 | ** For ERC-721 consider {ERC721Royalty} which clears the royalty information from storage on burn. 7 | 8 | == Contracts 9 | 10 | {{ERC2981}} 11 | -------------------------------------------------------------------------------- /contracts/utils/Calldata.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.3.0) (utils/Calldata.sol) 3 | 4 | pragma solidity ^0.8.20; 5 | 6 | /** 7 | * @dev Helper library for manipulating objects in calldata. 8 | */ 9 | library Calldata { 10 | // slither-disable-next-line write-after-write 11 | function emptyBytes() internal pure returns (bytes calldata result) { 12 | assembly ("memory-safe") { 13 | result.offset := 0 14 | result.length := 0 15 | } 16 | } 17 | 18 | // slither-disable-next-line write-after-write 19 | function emptyString() internal pure returns (string calldata result) { 20 | assembly ("memory-safe") { 21 | result.offset := 0 22 | result.length := 0 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /contracts/utils/Comparators.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.1.0) (utils/Comparators.sol) 3 | 4 | pragma solidity ^0.8.20; 5 | 6 | /** 7 | * @dev Provides a set of functions to compare values. 8 | * 9 | * _Available since v5.1._ 10 | */ 11 | library Comparators { 12 | function lt(uint256 a, uint256 b) internal pure returns (bool) { 13 | return a < b; 14 | } 15 | 16 | function gt(uint256 a, uint256 b) internal pure returns (bool) { 17 | return a > b; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/utils/Context.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) 3 | 4 | pragma solidity ^0.8.20; 5 | 6 | /** 7 | * @dev Provides information about the current execution context, including the 8 | * sender of the transaction and its data. While these are generally available 9 | * via msg.sender and msg.data, they should not be accessed in such a direct 10 | * manner, since when dealing with meta-transactions the account sending and 11 | * paying for execution may not be the actual sender (as far as an application 12 | * is concerned). 13 | * 14 | * This contract is only required for intermediate, library-like contracts. 15 | */ 16 | abstract contract Context { 17 | function _msgSender() internal view virtual returns (address) { 18 | return msg.sender; 19 | } 20 | 21 | function _msgData() internal view virtual returns (bytes calldata) { 22 | return msg.data; 23 | } 24 | 25 | function _contextSuffixLength() internal view virtual returns (uint256) { 26 | return 0; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /contracts/utils/Errors.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol) 3 | 4 | pragma solidity ^0.8.20; 5 | 6 | /** 7 | * @dev Collection of common custom errors used in multiple contracts 8 | * 9 | * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library. 10 | * It is recommended to avoid relying on the error API for critical functionality. 11 | * 12 | * _Available since v5.1._ 13 | */ 14 | library Errors { 15 | /** 16 | * @dev The ETH balance of the account is not enough to perform the operation. 17 | */ 18 | error InsufficientBalance(uint256 balance, uint256 needed); 19 | 20 | /** 21 | * @dev A call to an address target failed. The target may have reverted. 22 | */ 23 | error FailedCall(); 24 | 25 | /** 26 | * @dev The deployment failed. 27 | */ 28 | error FailedDeployment(); 29 | 30 | /** 31 | * @dev A necessary precompile is missing. 32 | */ 33 | error MissingPrecompile(address); 34 | } 35 | -------------------------------------------------------------------------------- /contracts/utils/cryptography/Hashes.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/Hashes.sol) 3 | 4 | pragma solidity ^0.8.20; 5 | 6 | /** 7 | * @dev Library of standard hash functions. 8 | * 9 | * _Available since v5.1._ 10 | */ 11 | library Hashes { 12 | /** 13 | * @dev Commutative Keccak256 hash of a sorted pair of bytes32. Frequently used when working with merkle proofs. 14 | * 15 | * NOTE: Equivalent to the `standardNodeHash` in our https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. 16 | */ 17 | function commutativeKeccak256(bytes32 a, bytes32 b) internal pure returns (bytes32) { 18 | return a < b ? efficientKeccak256(a, b) : efficientKeccak256(b, a); 19 | } 20 | 21 | /** 22 | * @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory. 23 | */ 24 | function efficientKeccak256(bytes32 a, bytes32 b) internal pure returns (bytes32 value) { 25 | assembly ("memory-safe") { 26 | mstore(0x00, a) 27 | mstore(0x20, b) 28 | value := keccak256(0x00, 0x40) 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /contracts/utils/cryptography/signers/AbstractSigner.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | /** 6 | * @dev Abstract contract for signature validation. 7 | * 8 | * Developers must implement {_rawSignatureValidation} and use it as the lowest-level signature validation mechanism. 9 | * 10 | * @custom:stateless 11 | */ 12 | abstract contract AbstractSigner { 13 | /** 14 | * @dev Signature validation algorithm. 15 | * 16 | * WARNING: Implementing a signature validation algorithm is a security-sensitive operation as it involves 17 | * cryptographic verification. It is important to review and test thoroughly before deployment. Consider 18 | * using one of the signature verification libraries (xref:api:utils/cryptography#ECDSA[ECDSA], 19 | * xref:api:utils/cryptography#P256[P256] or xref:api:utils/cryptography#RSA[RSA]). 20 | */ 21 | function _rawSignatureValidation(bytes32 hash, bytes calldata signature) internal view virtual returns (bool); 22 | } 23 | -------------------------------------------------------------------------------- /contracts/utils/cryptography/signers/SignerERC7702.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {AbstractSigner} from "./AbstractSigner.sol"; 6 | import {ECDSA} from "../ECDSA.sol"; 7 | 8 | /** 9 | * @dev Implementation of {AbstractSigner} for implementation for an EOA. Useful for ERC-7702 accounts. 10 | * 11 | * @custom:stateless 12 | */ 13 | abstract contract SignerERC7702 is AbstractSigner { 14 | /** 15 | * @dev Validates the signature using the EOA's address (i.e. `address(this)`). 16 | */ 17 | function _rawSignatureValidation( 18 | bytes32 hash, 19 | bytes calldata signature 20 | ) internal view virtual override returns (bool) { 21 | (address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecover(hash, signature); 22 | return address(this) == recovered && err == ECDSA.RecoverError.NoError; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /contracts/utils/cryptography/verifiers/ERC7913P256Verifier.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {P256} from "../../../utils/cryptography/P256.sol"; 6 | import {IERC7913SignatureVerifier} from "../../../interfaces/IERC7913.sol"; 7 | 8 | /** 9 | * @dev ERC-7913 signature verifier that support P256 (secp256r1) keys. 10 | */ 11 | contract ERC7913P256Verifier is IERC7913SignatureVerifier { 12 | /// @inheritdoc IERC7913SignatureVerifier 13 | function verify(bytes calldata key, bytes32 hash, bytes calldata signature) public view virtual returns (bytes4) { 14 | // Signature length may be 0x40 or 0x41. 15 | if (key.length == 0x40 && signature.length >= 0x40) { 16 | bytes32 qx = bytes32(key[0x00:0x20]); 17 | bytes32 qy = bytes32(key[0x20:0x40]); 18 | bytes32 r = bytes32(signature[0x00:0x20]); 19 | bytes32 s = bytes32(signature[0x20:0x40]); 20 | if (P256.verify(hash, r, s, qx, qy)) { 21 | return IERC7913SignatureVerifier.verify.selector; 22 | } 23 | } 24 | return 0xFFFFFFFF; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /contracts/utils/cryptography/verifiers/ERC7913RSAVerifier.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {RSA} from "../../../utils/cryptography/RSA.sol"; 6 | import {IERC7913SignatureVerifier} from "../../../interfaces/IERC7913.sol"; 7 | 8 | /** 9 | * @dev ERC-7913 signature verifier that support RSA keys. 10 | */ 11 | contract ERC7913RSAVerifier is IERC7913SignatureVerifier { 12 | /// @inheritdoc IERC7913SignatureVerifier 13 | function verify(bytes calldata key, bytes32 hash, bytes calldata signature) public view virtual returns (bytes4) { 14 | (bytes memory e, bytes memory n) = abi.decode(key, (bytes, bytes)); 15 | return 16 | RSA.pkcs1Sha256(abi.encodePacked(hash), signature, e, n) 17 | ? IERC7913SignatureVerifier.verify.selector 18 | : bytes4(0xFFFFFFFF); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /contracts/utils/introspection/ERC165.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol) 3 | 4 | pragma solidity ^0.8.20; 5 | 6 | import {IERC165} from "./IERC165.sol"; 7 | 8 | /** 9 | * @dev Implementation of the {IERC165} interface. 10 | * 11 | * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check 12 | * for the additional interface id that will be supported. For example: 13 | * 14 | * ```solidity 15 | * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { 16 | * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); 17 | * } 18 | * ``` 19 | */ 20 | abstract contract ERC165 is IERC165 { 21 | /// @inheritdoc IERC165 22 | function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { 23 | return interfaceId == type(IERC165).interfaceId; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /contracts/utils/introspection/IERC165.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) 3 | 4 | pragma solidity >=0.4.16; 5 | 6 | /** 7 | * @dev Interface of the ERC-165 standard, as defined in the 8 | * https://eips.ethereum.org/EIPS/eip-165[ERC]. 9 | * 10 | * Implementers can declare support of contract interfaces, which can then be 11 | * queried by others ({ERC165Checker}). 12 | * 13 | * For an implementation, see {ERC165}. 14 | */ 15 | interface IERC165 { 16 | /** 17 | * @dev Returns true if this contract implements the interface defined by 18 | * `interfaceId`. See the corresponding 19 | * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] 20 | * to learn more about how these ids are created. 21 | * 22 | * This function call must use less than 30 000 gas. 23 | */ 24 | function supportsInterface(bytes4 interfaceId) external view returns (bool); 25 | } 26 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | Documentation is hosted at https://docs.openzeppelin.com/contracts. 2 | 3 | All of the content for the site is in this repository. The guides are in the 4 | [docs](/docs) directory, and the API Reference is extracted from comments in 5 | the source code. If you want to help improve the content, this is the 6 | repository you should be contributing to. 7 | 8 | [`solidity-docgen`](https://github.com/OpenZeppelin/solidity-docgen) is the 9 | program that extracts the API Reference from source code. 10 | 11 | The [`docs.openzeppelin.com`](https://github.com/OpenZeppelin/docs.openzeppelin.com) 12 | repository hosts the configuration for the entire site, which includes 13 | documentation for all of the OpenZeppelin projects. 14 | 15 | To run the docs locally you should run `npm run docs:watch` on this 16 | repository. 17 | -------------------------------------------------------------------------------- /docs/antora.yml: -------------------------------------------------------------------------------- 1 | name: contracts 2 | title: Contracts 3 | version: 5.x 4 | prerelease: false 5 | nav: 6 | - modules/ROOT/nav.adoc 7 | - modules/api/nav.adoc 8 | -------------------------------------------------------------------------------- /docs/config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | 4 | /** @type import('solidity-docgen/dist/config').UserConfig */ 5 | module.exports = { 6 | outputDir: 'docs/modules/api/pages', 7 | templates: 'docs/templates', 8 | exclude: ['mocks'], 9 | pageExtension: '.adoc', 10 | pages: (_, file, config) => { 11 | // For each contract file, find the closest README.adoc and return its location as the output page path. 12 | const sourcesDir = path.resolve(config.root, config.sourcesDir); 13 | let dir = path.resolve(config.root, file.absolutePath); 14 | while (dir.startsWith(sourcesDir)) { 15 | dir = path.dirname(dir); 16 | if (fs.existsSync(path.join(dir, 'README.adoc'))) { 17 | return path.relative(sourcesDir, dir) + config.pageExtension; 18 | } 19 | } 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /docs/modules/ROOT/images/erc4626-attack-3a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/docs/modules/ROOT/images/erc4626-attack-3a.png -------------------------------------------------------------------------------- /docs/modules/ROOT/images/erc4626-attack-3b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/docs/modules/ROOT/images/erc4626-attack-3b.png -------------------------------------------------------------------------------- /docs/modules/ROOT/images/erc4626-attack-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/docs/modules/ROOT/images/erc4626-attack-6.png -------------------------------------------------------------------------------- /docs/modules/ROOT/images/erc4626-attack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/docs/modules/ROOT/images/erc4626-attack.png -------------------------------------------------------------------------------- /docs/modules/ROOT/images/erc4626-deposit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/docs/modules/ROOT/images/erc4626-deposit.png -------------------------------------------------------------------------------- /docs/modules/ROOT/images/erc4626-mint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/docs/modules/ROOT/images/erc4626-mint.png -------------------------------------------------------------------------------- /docs/modules/ROOT/images/erc4626-rate-linear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/docs/modules/ROOT/images/erc4626-rate-linear.png -------------------------------------------------------------------------------- /docs/modules/ROOT/images/erc4626-rate-loglog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/docs/modules/ROOT/images/erc4626-rate-loglog.png -------------------------------------------------------------------------------- /docs/modules/ROOT/images/erc4626-rate-loglogext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/docs/modules/ROOT/images/erc4626-rate-loglogext.png -------------------------------------------------------------------------------- /docs/modules/ROOT/images/tally-exec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/docs/modules/ROOT/images/tally-exec.png -------------------------------------------------------------------------------- /docs/modules/ROOT/images/tally-vote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/docs/modules/ROOT/images/tally-vote.png -------------------------------------------------------------------------------- /docs/modules/ROOT/nav.adoc: -------------------------------------------------------------------------------- 1 | * xref:index.adoc[Overview] 2 | * xref:wizard.adoc[Wizard] 3 | * xref:extending-contracts.adoc[Extending Contracts] 4 | * xref:upgradeable.adoc[Using with Upgrades] 5 | 6 | * xref:backwards-compatibility.adoc[Backwards Compatibility] 7 | 8 | * xref:access-control.adoc[Access Control] 9 | 10 | * xref:tokens.adoc[Tokens] 11 | ** xref:erc20.adoc[ERC-20] 12 | *** xref:erc20-supply.adoc[Creating Supply] 13 | ** xref:erc721.adoc[ERC-721] 14 | ** xref:erc1155.adoc[ERC-1155] 15 | ** xref:erc4626.adoc[ERC-4626] 16 | ** xref:erc6909.adoc[ERC-6909] 17 | 18 | * xref:governance.adoc[Governance] 19 | 20 | * xref:utilities.adoc[Utilities] 21 | 22 | * xref:subgraphs::index.adoc[Subgraphs] 23 | 24 | * xref:faq.adoc[FAQ] 25 | -------------------------------------------------------------------------------- /docs/modules/ROOT/pages/faq.adoc: -------------------------------------------------------------------------------- 1 | = Frequently Asked Questions 2 | 3 | == Can I restrict a function to EOAs only? 4 | 5 | When calling external addresses from your contract it is unsafe to assume that an address is an externally-owned account (EOA) and not a contract. Attempting to prevent calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract constructor. 6 | 7 | Although checking that the address has code, `address.code.length > 0`, may seem to differentiate contracts from EOAs, it can only say that an address is currently a contract, and its negation (that an address is not currently a contract) does not imply that the address is an EOA. Some counterexamples are: 8 | 9 | - address of a contract in construction 10 | - address where a contract will be created 11 | - address where a contract lived, but was destroyed 12 | 13 | Furthermore, an address will be considered a contract within the same transaction where it is scheduled for destruction by `SELFDESTRUCT`, which only has an effect at the end of the entire transaction. 14 | -------------------------------------------------------------------------------- /docs/modules/ROOT/pages/wizard.adoc: -------------------------------------------------------------------------------- 1 | = Contracts Wizard 2 | :page-notoc: 3 | 4 | Not sure where to start? Use the interactive generator below to bootstrap your 5 | contract and learn about the components offered in OpenZeppelin Contracts. 6 | 7 | TIP: Place the resulting contract in your `contracts` or `src` directory in order to compile it with a tool like Hardhat or Foundry. Consider reading our guide on xref:learn::developing-smart-contracts.adoc[Developing Smart Contracts] for more guidance! 8 | 9 | ++++ 10 | 11 | 12 | 13 | ++++ 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/templates/page.hbs: -------------------------------------------------------------------------------- 1 | :github-icon: pass:[] 2 | {{#with-prelude}} 3 | {{readme (readme-path)}} 4 | {{/with-prelude}} 5 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import js from '@eslint/js'; 2 | import { includeIgnoreFile } from '@eslint/compat'; 3 | import prettier from 'eslint-config-prettier'; 4 | import globals from 'globals'; 5 | import path from 'path'; 6 | 7 | export default [ 8 | js.configs.recommended, 9 | prettier, 10 | { 11 | languageOptions: { 12 | ecmaVersion: 2022, 13 | globals: { 14 | ...globals.browser, 15 | ...globals.mocha, 16 | ...globals.node, 17 | artifacts: 'readonly', 18 | contract: 'readonly', 19 | web3: 'readonly', 20 | extendEnvironment: 'readonly', 21 | expect: 'readonly', 22 | }, 23 | }, 24 | }, 25 | includeIgnoreFile(path.resolve(import.meta.dirname, '.gitignore')), 26 | ]; 27 | -------------------------------------------------------------------------------- /foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | solc_version = '0.8.27' 3 | evm_version = 'prague' 4 | optimizer = true 5 | optimizer-runs = 200 6 | src = 'contracts' 7 | out = 'out' 8 | libs = ['node_modules', 'lib'] 9 | test = 'test' 10 | cache_path = 'cache_forge' 11 | fs_permissions = [{ access = "read", path = "./test/bin" }] 12 | 13 | [fuzz] 14 | runs = 5000 15 | max_test_rejects = 150000 16 | -------------------------------------------------------------------------------- /fv-requirements.txt: -------------------------------------------------------------------------------- 1 | certora-cli==4.13.1 2 | # File uses a custom name (fv-requirements.txt) so that it isn't picked by Netlify's build 3 | # whose latest Python version is 0.3.8, incompatible with most recent versions of Halmos 4 | halmos==0.2.6 5 | -------------------------------------------------------------------------------- /hardhat/async-test-sanity.js: -------------------------------------------------------------------------------- 1 | process.on('unhandledRejection', reason => { 2 | // If the reason is already an Error object, throw it directly to preserve the stack trace. 3 | if (reason instanceof Error) { 4 | throw reason; 5 | } else { 6 | // If the reason is not an Error (e.g., a string, number, or other primitive), 7 | // create a new Error object with the reason as its message. 8 | throw new Error(`Unhandled rejection: ${reason}`); 9 | } 10 | }); 11 | -------------------------------------------------------------------------------- /hardhat/env-artifacts.js: -------------------------------------------------------------------------------- 1 | const { HardhatError } = require('hardhat/internal/core/errors'); 2 | 3 | function isExpectedError(e, suffix) { 4 | // HH700: Artifact not found - from https://hardhat.org/hardhat-runner/docs/errors#HH700 5 | return HardhatError.isHardhatError(e) && e.number === 700 && suffix !== ''; 6 | } 7 | 8 | // Modifies the artifact require functions so that instead of X it loads the XUpgradeable contract. 9 | // This allows us to run the same test suite on both the original and the transpiled and renamed Upgradeable contracts. 10 | extendEnvironment(hre => { 11 | const suffixes = ['UpgradeableWithInit', 'Upgradeable', '']; 12 | 13 | // Ethers 14 | const originalReadArtifact = hre.artifacts.readArtifact; 15 | hre.artifacts.readArtifact = async function (name) { 16 | for (const suffix of suffixes) { 17 | try { 18 | return await originalReadArtifact.call(this, name + suffix); 19 | } catch (e) { 20 | if (isExpectedError(e, suffix)) { 21 | continue; 22 | } else { 23 | throw e; 24 | } 25 | } 26 | } 27 | throw new Error('Unreachable'); 28 | }; 29 | }); 30 | -------------------------------------------------------------------------------- /hardhat/remappings.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const { task } = require('hardhat/config'); 3 | const { TASK_COMPILE_GET_REMAPPINGS } = require('hardhat/builtin-tasks/task-names'); 4 | 5 | task(TASK_COMPILE_GET_REMAPPINGS).setAction((taskArgs, env, runSuper) => 6 | runSuper().then(remappings => 7 | Object.assign( 8 | remappings, 9 | Object.fromEntries( 10 | fs 11 | .readFileSync('remappings.txt', 'utf-8') 12 | .split('\n') 13 | .filter(Boolean) 14 | .map(line => line.trim().split('=')), 15 | ), 16 | ), 17 | ), 18 | ); 19 | -------------------------------------------------------------------------------- /hardhat/skip-foundry-tests.js: -------------------------------------------------------------------------------- 1 | const { subtask } = require('hardhat/config'); 2 | const { TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS } = require('hardhat/builtin-tasks/task-names'); 3 | 4 | subtask(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS).setAction(async (_, __, runSuper) => 5 | (await runSuper()).filter(path => !path.endsWith('.t.sol')), 6 | ); 7 | -------------------------------------------------------------------------------- /hardhat/task-test-get-files.js: -------------------------------------------------------------------------------- 1 | const { internalTask } = require('hardhat/config'); 2 | const { TASK_TEST_GET_TEST_FILES } = require('hardhat/builtin-tasks/task-names'); 3 | 4 | // Modifies `hardhat test` to skip the proxy tests after proxies are removed by the transpiler for upgradeability. 5 | 6 | internalTask(TASK_TEST_GET_TEST_FILES).setAction(async (args, hre, runSuper) => { 7 | const path = require('path'); 8 | const { promises: fs } = require('fs'); 9 | 10 | const hasProxies = await fs 11 | .access(path.join(hre.config.paths.sources, 'proxy/Proxy.sol')) 12 | .then(() => true) 13 | .catch(() => false); 14 | 15 | const ignoredIfProxy = [ 16 | 'proxy/beacon/BeaconProxy.test.js', 17 | 'proxy/beacon/UpgradeableBeacon.test.js', 18 | 'proxy/ERC1967/ERC1967Proxy.test.js', 19 | 'proxy/transparent/ProxyAdmin.test.js', 20 | 'proxy/transparent/TransparentUpgradeableProxy.test.js', 21 | 'proxy/utils/UUPSUpgradeable.test.js', 22 | ].map(p => path.join(hre.config.paths.tests, p)); 23 | 24 | return (await runSuper(args)).filter(file => hasProxies || !ignoredIfProxy.includes(file)); 25 | }); 26 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | command = "npm run docs" 3 | publish = "build/site" 4 | -------------------------------------------------------------------------------- /remappings.txt: -------------------------------------------------------------------------------- 1 | @openzeppelin/contracts/=contracts/ 2 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["github>OpenZeppelin/configs"], 3 | "labels": ["ignore-changeset"] 4 | } 5 | -------------------------------------------------------------------------------- /scripts/checks/compare-layout.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const { getStorageUpgradeReport } = require('@openzeppelin/upgrades-core/dist/storage'); 3 | 4 | const { ref, head } = require('yargs').argv; 5 | 6 | const oldLayout = JSON.parse(fs.readFileSync(ref)); 7 | const newLayout = JSON.parse(fs.readFileSync(head)); 8 | 9 | for (const name in oldLayout) { 10 | if (name in newLayout) { 11 | const report = getStorageUpgradeReport(oldLayout[name], newLayout[name], {}); 12 | if (!report.ok) { 13 | console.log(`Storage layout incompatibility found in ${name}:`); 14 | console.log(report.explain()); 15 | process.exitCode = 1; 16 | } 17 | } else { 18 | console.log(`WARNING: ${name} is missing from the current branch`); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /scripts/checks/coverage.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | export COVERAGE=true 6 | export FOUNDRY_FUZZ_RUNS=10 7 | 8 | . scripts/set-max-old-space-size.sh 9 | 10 | # Hardhat coverage 11 | hardhat coverage 12 | 13 | if [ "${CI:-"false"}" == "true" ]; then 14 | # Foundry coverage 15 | forge coverage --report lcov --ir-minimum 16 | # Remove zero hits 17 | if [[ "$OSTYPE" == "darwin"* ]]; then 18 | sed -i '' '/,0/d' lcov.info 19 | else 20 | sed -i '/,0/d' lcov.info 21 | fi 22 | fi 23 | 24 | # Reports are then uploaded to Codecov automatically by workflow, and merged. 25 | -------------------------------------------------------------------------------- /scripts/checks/extract-layout.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const { findAll, astDereferencer, srcDecoder } = require('solidity-ast/utils'); 3 | const { extractStorageLayout } = require('@openzeppelin/upgrades-core/dist/storage/extract'); 4 | 5 | const { _ } = require('yargs').argv; 6 | 7 | const skipPath = ['contracts/mocks/', 'contracts-exposed/']; 8 | const skipKind = ['interface', 'library']; 9 | 10 | function extractLayouts(path) { 11 | const layout = {}; 12 | const { input, output } = JSON.parse(fs.readFileSync(path)); 13 | 14 | const decoder = srcDecoder(input, output); 15 | const deref = astDereferencer(output); 16 | 17 | for (const src in output.contracts) { 18 | if (skipPath.some(prefix => src.startsWith(prefix))) { 19 | continue; 20 | } 21 | 22 | for (const contractDef of findAll('ContractDefinition', output.sources[src].ast)) { 23 | if (skipKind.includes(contractDef.contractKind)) { 24 | continue; 25 | } 26 | 27 | layout[contractDef.name] = extractStorageLayout( 28 | contractDef, 29 | decoder, 30 | deref, 31 | output.contracts[src][contractDef.name].storageLayout, 32 | ); 33 | } 34 | } 35 | return layout; 36 | } 37 | 38 | console.log(JSON.stringify(Object.assign(..._.map(extractLayouts)))); 39 | -------------------------------------------------------------------------------- /scripts/checks/generation.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | npm run generate 6 | git diff -R --exit-code 7 | -------------------------------------------------------------------------------- /scripts/generate/format-lines.js: -------------------------------------------------------------------------------- 1 | function formatLines(...lines) { 2 | return [...indentEach(0, lines)].join('\n') + '\n'; 3 | } 4 | 5 | function* indentEach(indent, lines) { 6 | for (const line of lines) { 7 | if (Array.isArray(line)) { 8 | yield* indentEach(indent + 1, line); 9 | } else { 10 | const padding = ' '.repeat(indent); 11 | yield* line.split('\n').map(subline => (subline === '' ? '' : padding + subline)); 12 | } 13 | } 14 | } 15 | 16 | module.exports = formatLines; 17 | -------------------------------------------------------------------------------- /scripts/generate/helpers/sanitize.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | address: expr => `and(${expr}, shr(96, not(0)))`, 3 | bool: expr => `iszero(iszero(${expr}))`, 4 | bytes: (expr, size) => `and(${expr}, shl(${256 - 8 * size}, not(0)))`, 5 | }; 6 | -------------------------------------------------------------------------------- /scripts/generate/templates/Arrays.opts.js: -------------------------------------------------------------------------------- 1 | const TYPES = [ 2 | { name: 'address', isValueType: true }, 3 | { name: 'bytes32', isValueType: true }, 4 | { name: 'uint256', isValueType: true }, 5 | { name: 'bytes', isValueType: false }, 6 | { name: 'string', isValueType: false }, 7 | ]; 8 | 9 | module.exports = { TYPES }; 10 | -------------------------------------------------------------------------------- /scripts/generate/templates/Checkpoints.opts.js: -------------------------------------------------------------------------------- 1 | // OPTIONS 2 | const VALUE_SIZES = [224, 208, 160]; 3 | 4 | const defaultOpts = size => ({ 5 | historyTypeName: `Trace${size}`, 6 | checkpointTypeName: `Checkpoint${size}`, 7 | checkpointFieldName: '_checkpoints', 8 | keyTypeName: `uint${256 - size}`, 9 | keyFieldName: '_key', 10 | valueTypeName: `uint${size}`, 11 | valueFieldName: '_value', 12 | }); 13 | 14 | module.exports = { 15 | VALUE_SIZES, 16 | OPTS: VALUE_SIZES.map(size => defaultOpts(size)), 17 | }; 18 | -------------------------------------------------------------------------------- /scripts/generate/templates/MerkleProof.opts.js: -------------------------------------------------------------------------------- 1 | const { product } = require('../../helpers'); 2 | 3 | const OPTS = product( 4 | [ 5 | { suffix: '', location: 'memory' }, 6 | { suffix: 'Calldata', location: 'calldata' }, 7 | ], 8 | [{ visibility: 'pure' }, { visibility: 'view', hash: 'hasher' }], 9 | ).map(objs => Object.assign({}, ...objs)); 10 | 11 | module.exports = { OPTS }; 12 | -------------------------------------------------------------------------------- /scripts/generate/templates/Packing.opts.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | SIZES: [1, 2, 4, 6, 8, 10, 12, 16, 20, 22, 24, 28, 32], 3 | }; 4 | -------------------------------------------------------------------------------- /scripts/generate/templates/Slot.opts.js: -------------------------------------------------------------------------------- 1 | const { capitalize } = require('../../helpers'); 2 | 3 | const TYPES = [ 4 | { type: 'address', isValueType: true }, 5 | { type: 'bool', isValueType: true, name: 'Boolean' }, 6 | { type: 'bytes32', isValueType: true, variants: ['bytes4'] }, 7 | { type: 'uint256', isValueType: true, variants: ['uint32'] }, 8 | { type: 'int256', isValueType: true, variants: ['int32'] }, 9 | { type: 'string', isValueType: false }, 10 | { type: 'bytes', isValueType: false }, 11 | ].map(type => Object.assign(type, { name: type.name ?? capitalize(type.type) })); 12 | 13 | Object.assign(TYPES, Object.fromEntries(TYPES.map(entry => [entry.type, entry]))); 14 | 15 | module.exports = { TYPES }; 16 | -------------------------------------------------------------------------------- /scripts/generate/templates/TransientSlotMock.js: -------------------------------------------------------------------------------- 1 | const format = require('../format-lines'); 2 | const { TYPES } = require('./Slot.opts'); 3 | 4 | const header = `\ 5 | pragma solidity ^0.8.24; 6 | 7 | import {Multicall} from "../utils/Multicall.sol"; 8 | import {TransientSlot} from "../utils/TransientSlot.sol"; 9 | `; 10 | 11 | const transient = ({ type, name }) => `\ 12 | event ${name}Value(bytes32 slot, ${type} value); 13 | 14 | function tload${name}(bytes32 slot) public { 15 | emit ${name}Value(slot, slot.as${name}().tload()); 16 | } 17 | 18 | function tstore(bytes32 slot, ${type} value) public { 19 | slot.as${name}().tstore(value); 20 | } 21 | `; 22 | 23 | // GENERATE 24 | module.exports = format( 25 | header, 26 | 'contract TransientSlotMock is Multicall {', 27 | format( 28 | [].concat( 29 | 'using TransientSlot for *;', 30 | '', 31 | TYPES.filter(type => type.isValueType).map(type => transient(type)), 32 | ), 33 | ).trimEnd(), 34 | '}', 35 | ); 36 | -------------------------------------------------------------------------------- /scripts/generate/templates/conversion.js: -------------------------------------------------------------------------------- 1 | function toBytes32(type, value) { 2 | switch (type) { 3 | case 'bytes32': 4 | return value; 5 | case 'uint256': 6 | return `bytes32(${value})`; 7 | case 'address': 8 | return `bytes32(uint256(uint160(${value})))`; 9 | default: 10 | throw new Error(`Conversion from ${type} to bytes32 not supported`); 11 | } 12 | } 13 | 14 | function fromBytes32(type, value) { 15 | switch (type) { 16 | case 'bytes32': 17 | return value; 18 | case 'uint256': 19 | return `uint256(${value})`; 20 | case 'address': 21 | return `address(uint160(uint256(${value})))`; 22 | default: 23 | throw new Error(`Conversion from bytes32 to ${type} not supported`); 24 | } 25 | } 26 | 27 | module.exports = { 28 | toBytes32, 29 | fromBytes32, 30 | }; 31 | -------------------------------------------------------------------------------- /scripts/git-user-config.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail -x 4 | 5 | git config user.name 'github-actions' 6 | git config user.email '41898282+github-actions[bot]@users.noreply.github.com' 7 | -------------------------------------------------------------------------------- /scripts/helpers.js: -------------------------------------------------------------------------------- 1 | const iterate = require('../test/helpers/iterate'); 2 | const strings = require('../test/helpers/strings'); 3 | 4 | module.exports = { 5 | ...iterate, 6 | ...strings, 7 | }; 8 | -------------------------------------------------------------------------------- /scripts/prepack.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | shopt -s globstar 5 | 6 | # cross platform `mkdir -p` 7 | mkdirp() { 8 | node -e "fs.mkdirSync('$1', { recursive: true })" 9 | } 10 | 11 | # cd to the root of the repo 12 | cd "$(git rev-parse --show-toplevel)" 13 | 14 | npm run clean 15 | 16 | env COMPILE_MODE=production npm run compile 17 | 18 | mkdirp contracts/build/contracts 19 | cp artifacts/contracts/**/*.json contracts/build/contracts 20 | rm contracts/build/contracts/*.dbg.json 21 | node scripts/remove-ignored-artifacts.js 22 | 23 | cp README.md contracts/ 24 | -------------------------------------------------------------------------------- /scripts/prepare-docs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | shopt -s globstar 5 | 6 | OUTDIR="$(node -p 'require("./docs/config.js").outputDir')" 7 | 8 | if [ ! -d node_modules ]; then 9 | npm ci 10 | fi 11 | 12 | rm -rf "$OUTDIR" 13 | 14 | hardhat docgen 15 | 16 | # copy examples and adjust imports 17 | examples_source_dir="contracts/mocks/docs" 18 | examples_target_dir="docs/modules/api/examples" 19 | 20 | for f in "$examples_source_dir"/**/*.sol; do 21 | name="${f/#"$examples_source_dir"/}" 22 | mkdir -p "$examples_target_dir/$(dirname "$name")" 23 | sed -Ee '/^import/s|"(\.\./)+|"@openzeppelin/contracts/|' "$f" > "$examples_target_dir/$name" 24 | done 25 | 26 | node scripts/gen-nav.js "$OUTDIR" > "$OUTDIR/../nav.adoc" 27 | -------------------------------------------------------------------------------- /scripts/release/format-changelog.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // Adjusts the format of the changelog that changesets generates. 4 | // This is run automatically when npm version is run. 5 | 6 | const fs = require('fs'); 7 | const changelog = fs.readFileSync('CHANGELOG.md', 'utf8'); 8 | 9 | // Groups: 10 | // - 1: Pull Request Number and URL 11 | // - 2: Changeset entry 12 | const RELEASE_LINE_REGEX = /^- (\[#.*?\]\(.*?\))?.*?! - (.*)$/gm; 13 | 14 | // Captures vX.Y.Z or vX.Y.Z-rc.W 15 | const VERSION_TITLE_REGEX = /^## (\d+\.\d+\.\d+(-rc\.\d+)?)$/gm; 16 | 17 | const isPrerelease = process.env.PRERELEASE === 'true'; 18 | 19 | const formatted = changelog 20 | // Remove titles 21 | .replace(/^### Major Changes\n\n/gm, '') 22 | .replace(/^### Minor Changes\n\n/gm, '') 23 | .replace(/^### Patch Changes\n\n/gm, '') 24 | // Remove extra whitespace between items 25 | .replace(/^(- \[.*\n)\n(?=-)/gm, '$1') 26 | // Format each release line 27 | .replace(RELEASE_LINE_REGEX, (_, pr, entry) => (pr ? `- ${entry} (${pr})` : `- ${entry}`)) 28 | // Add date to new version 29 | .replace(VERSION_TITLE_REGEX, `\n## $1 (${new Date().toISOString().split('T')[0]})`) 30 | // Conditionally allow vX.Y.Z-rc.W sections only in prerelease 31 | .replace(/^## \d\.\d\.\d-rc\S+[^]+?(?=^#)/gm, section => (isPrerelease ? section : '')); 32 | 33 | fs.writeFileSync('CHANGELOG.md', formatted); 34 | -------------------------------------------------------------------------------- /scripts/release/synchronize-versions.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // Synchronizes the version in contracts/package.json with the one in package.json. 4 | // This is run automatically when npm version is run. 5 | 6 | const fs = require('fs'); 7 | 8 | setVersion('package.json', 'contracts/package.json'); 9 | 10 | function setVersion(from, to) { 11 | const fromJson = JSON.parse(fs.readFileSync(from)); 12 | const toJson = JSON.parse(fs.readFileSync(to)); 13 | toJson.version = fromJson.version; 14 | fs.writeFileSync(to, JSON.stringify(toJson, null, 2) + '\n'); 15 | } 16 | -------------------------------------------------------------------------------- /scripts/release/version.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | changeset version 6 | 7 | scripts/release/format-changelog.js 8 | scripts/release/synchronize-versions.js 9 | scripts/release/update-comment.js 10 | 11 | oz-docs update-version 12 | -------------------------------------------------------------------------------- /scripts/release/workflow/exit-prerelease.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | npx changeset pre exit rc 6 | git add . 7 | git commit -m "Exit release candidate" 8 | git push origin 9 | -------------------------------------------------------------------------------- /scripts/release/workflow/integrity-check.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | CHECKSUMS="$RUNNER_TEMP/checksums.txt" 6 | 7 | # Extract tarball content into a tmp directory 8 | tar xf "$TARBALL" -C "$RUNNER_TEMP" 9 | 10 | # Move to extracted directory 11 | cd "$RUNNER_TEMP/package" 12 | 13 | # Checksum all Solidity files 14 | find . -type f -name "*.sol" | xargs shasum > "$CHECKSUMS" 15 | 16 | # Back to directory with git contents 17 | cd "$GITHUB_WORKSPACE/contracts" 18 | 19 | # Check against tarball contents 20 | shasum -c "$CHECKSUMS" 21 | -------------------------------------------------------------------------------- /scripts/release/workflow/pack.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | dist_tag() { 6 | PACKAGE_JSON_NAME="$(jq -r .name ./package.json)" 7 | LATEST_NPM_VERSION="$(npm info "$PACKAGE_JSON_NAME" version)" 8 | PACKAGE_JSON_VERSION="$(jq -r .version ./package.json)" 9 | 10 | if [ "$PRERELEASE" = "true" ]; then 11 | echo "next" 12 | elif npx semver -r ">$LATEST_NPM_VERSION" "$PACKAGE_JSON_VERSION" > /dev/null; then 13 | echo "latest" 14 | else 15 | # This is a patch for an older version 16 | # npm can't publish without a tag 17 | echo "tmp" 18 | fi 19 | } 20 | 21 | cd contracts 22 | TARBALL="$(npm pack | tee /dev/stderr | tail -1)" 23 | echo "tarball_name=$TARBALL" >> $GITHUB_OUTPUT 24 | echo "tarball=$(pwd)/$TARBALL" >> $GITHUB_OUTPUT 25 | echo "tag=$(dist_tag)" >> $GITHUB_OUTPUT 26 | cd .. 27 | -------------------------------------------------------------------------------- /scripts/release/workflow/publish.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | PACKAGE_JSON_NAME="$(tar xfO "$TARBALL" package/package.json | jq -r .name)" 6 | PACKAGE_JSON_VERSION="$(tar xfO "$TARBALL" package/package.json | jq -r .version)" 7 | 8 | # Intentionally escape $ to avoid interpolation and writing the token to disk 9 | echo "//registry.npmjs.org/:_authToken=\${NPM_TOKEN}" > .npmrc 10 | 11 | # Actual publish 12 | npm publish "$TARBALL" --tag "$TAG" 13 | 14 | # Clean up tags 15 | delete_tag() { 16 | npm dist-tag rm "$PACKAGE_JSON_NAME" "$1" 17 | } 18 | 19 | if [ "$TAG" = tmp ]; then 20 | delete_tag "$TAG" 21 | elif [ "$TAG" = latest ]; then 22 | # Delete the next tag if it exists and is a prerelease for what is currently being published 23 | if npm dist-tag ls "$PACKAGE_JSON_NAME" | grep -q "next: $PACKAGE_JSON_VERSION"; then 24 | delete_tag next 25 | fi 26 | fi 27 | -------------------------------------------------------------------------------- /scripts/release/workflow/rerun.js: -------------------------------------------------------------------------------- 1 | module.exports = ({ github, context }) => 2 | github.rest.actions.createWorkflowDispatch({ 3 | owner: context.repo.owner, 4 | repo: context.repo.repo, 5 | workflow_id: 'release-cycle.yml', 6 | ref: process.env.REF || process.env.GITHUB_REF_NAME, 7 | }); 8 | -------------------------------------------------------------------------------- /scripts/release/workflow/set-changesets-pr-title.js: -------------------------------------------------------------------------------- 1 | const { coerce, inc, rsort } = require('semver'); 2 | const { join } = require('path'); 3 | const { version } = require(join(__dirname, '../../../package.json')); 4 | 5 | module.exports = async ({ core }) => { 6 | // Variables not in the context 7 | const refName = process.env.GITHUB_REF_NAME; 8 | 9 | // Compare package.json version's next patch vs. first version patch 10 | // A recently opened branch will give the next patch for the previous minor 11 | // So, we get the max against the patch 0 of the release branch's version 12 | const branchPatch0 = coerce(refName.replace('release-v', '')).version; 13 | const packageJsonNextPatch = inc(version, 'patch'); 14 | const [nextVersion] = rsort([branchPatch0, packageJsonNextPatch], false); 15 | 16 | core.exportVariable('TITLE', `Release v${nextVersion}`); 17 | }; 18 | -------------------------------------------------------------------------------- /scripts/release/workflow/start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | # Set changeset status location 6 | # This is needed because `changeset status --output` only works with relative routes 7 | CHANGESETS_STATUS_JSON="$(realpath --relative-to=. "$RUNNER_TEMP/status.json")" 8 | 9 | # Save changeset status to temp file 10 | npx changeset status --output="$CHANGESETS_STATUS_JSON" 11 | 12 | # Defensive assertion. SHOULD NOT BE REACHED 13 | if [ "$(jq '.releases | length' "$CHANGESETS_STATUS_JSON")" != 1 ]; then 14 | echo "::error file=$CHANGESETS_STATUS_JSON::The status doesn't contain only 1 release" 15 | exit 1; 16 | fi; 17 | 18 | # Create branch 19 | BRANCH_SUFFIX="$(jq -r '.releases[0].newVersion | gsub("\\.\\d+$"; "")' $CHANGESETS_STATUS_JSON)" 20 | RELEASE_BRANCH="release-v$BRANCH_SUFFIX" 21 | git checkout -b "$RELEASE_BRANCH" 22 | 23 | # Output branch 24 | echo "branch=$RELEASE_BRANCH" >> $GITHUB_OUTPUT 25 | 26 | # Enter in prerelease state 27 | npx changeset pre enter rc 28 | git add . 29 | git commit -m "Start release candidate" 30 | 31 | # Push branch 32 | if ! git push origin "$RELEASE_BRANCH"; then 33 | echo "::error file=scripts/release/start.sh::Can't push $RELEASE_BRANCH. Did you forget to run this workflow from $RELEASE_BRANCH?" 34 | exit 1 35 | fi 36 | -------------------------------------------------------------------------------- /scripts/set-max-old-space-size.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # This script sets the node `--max-old-space-size` to 8192 if it is not set already. 4 | # All existing `NODE_OPTIONS` are retained as is. 5 | 6 | export NODE_OPTIONS="${NODE_OPTIONS:-}" 7 | 8 | if [ "${NODE_OPTIONS##*--max-old-space-size*}" = "$NODE_OPTIONS" ]; then 9 | export NODE_OPTIONS="${NODE_OPTIONS} --max-old-space-size=8192" 10 | fi 11 | -------------------------------------------------------------------------------- /scripts/solc-versions.js: -------------------------------------------------------------------------------- 1 | const { exec } = require('child_process'); 2 | const semver = require('semver'); 3 | const { range } = require('./helpers'); 4 | 5 | module.exports = { 6 | versions: ['0.4.26', '0.5.16', '0.6.12', '0.7.6', '0.8.30'] 7 | .map(semver.parse) 8 | .flatMap(({ major, minor, patch }) => range(patch + 1).map(p => `${major}.${minor}.${p}`)), 9 | compile: (source, version) => 10 | new Promise((resolve, reject) => 11 | exec(`forge build ${source} --use ${version} --out out/solc-${version}`, error => 12 | error ? reject(error) : resolve(), 13 | ), 14 | ), 15 | }; 16 | -------------------------------------------------------------------------------- /scripts/solhint-custom/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solhint-plugin-openzeppelin", 3 | "version": "0.0.0", 4 | "private": true, 5 | "dependencies": { 6 | "minimatch": "^3.1.2" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /scripts/upgradeable/patch-apply.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | DIRNAME="$(dirname -- "${BASH_SOURCE[0]}")" 6 | PATCH="$DIRNAME/upgradeable.patch" 7 | 8 | error() { 9 | echo Error: "$*" >&2 10 | exit 1 11 | } 12 | 13 | if ! git diff-files --quiet ":!$PATCH" || ! git diff-index --quiet HEAD ":!$PATCH"; then 14 | error "Repository must have no staged or unstaged changes" 15 | fi 16 | 17 | if ! git apply -3 "$PATCH"; then 18 | error "Fix conflicts and run $DIRNAME/patch-save.sh" 19 | fi 20 | -------------------------------------------------------------------------------- /scripts/upgradeable/patch-save.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | DIRNAME="$(dirname -- "${BASH_SOURCE[0]}")" 6 | PATCH="$DIRNAME/upgradeable.patch" 7 | 8 | error() { 9 | echo Error: "$*" >&2 10 | exit 1 11 | } 12 | 13 | if ! git diff-files --quiet ":!$PATCH"; then 14 | error "Unstaged changes. Stage to include in patch or temporarily stash." 15 | fi 16 | 17 | git diff-index --cached --patch --output="$PATCH" HEAD 18 | git restore --staged --worktree ":!$PATCH" 19 | -------------------------------------------------------------------------------- /slither.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "detectors_to_run": "arbitrary-send-erc20,array-by-reference,incorrect-shift,name-reused,rtlo,suicidal,uninitialized-state,uninitialized-storage,arbitrary-send-erc20-permit,controlled-array-length,controlled-delegatecall,delegatecall-loop,msg-value-loop,reentrancy-eth,unchecked-transfer,weak-prng,domain-separator-collision,erc20-interface,erc721-interface,locked-ether,mapping-deletion,shadowing-abstract,tautology,write-after-write,boolean-cst,reentrancy-no-eth,reused-constructor,tx-origin,unchecked-lowlevel,unchecked-send,variable-scope,void-cst,events-access,events-maths,incorrect-unary,boolean-equal,cyclomatic-complexity,deprecated-standards,erc20-indexed,function-init-state,pragma,unused-state,reentrancy-unlimited-gas,constable-states,immutable-states,var-read-using-this", 3 | "filter_paths": "contracts/mocks,contracts/vendor,contracts-exposed" 4 | } 5 | -------------------------------------------------------------------------------- /solhint.config.js: -------------------------------------------------------------------------------- 1 | const customRules = require('solhint-plugin-openzeppelin'); 2 | 3 | const rules = [ 4 | 'avoid-tx-origin', 5 | 'const-name-snakecase', 6 | 'contract-name-capwords', 7 | 'event-name-capwords', 8 | 'max-states-count', 9 | 'explicit-types', 10 | 'func-name-mixedcase', 11 | 'func-param-name-mixedcase', 12 | 'imports-on-top', 13 | 'modifier-name-mixedcase', 14 | 'no-console', 15 | 'no-global-import', 16 | 'no-unused-vars', 17 | 'quotes', 18 | 'use-forbidden-name', 19 | 'var-name-mixedcase', 20 | 'visibility-modifier-order', 21 | 'interface-starts-with-i', 22 | 'duplicated-imports', 23 | ...customRules.map(r => `openzeppelin/${r.ruleId}`), 24 | ]; 25 | 26 | module.exports = { 27 | plugins: ['openzeppelin'], 28 | rules: Object.fromEntries(rules.map(r => [r, 'error'])), 29 | }; 30 | -------------------------------------------------------------------------------- /test/TESTING.md: -------------------------------------------------------------------------------- 1 | ## Testing 2 | 3 | Unit tests are critical to OpenZeppelin Contracts. They help ensure code quality and mitigate against security vulnerabilities. The directory structure within the `/test` directory corresponds to the `/contracts` directory. 4 | -------------------------------------------------------------------------------- /test/access/AccessControl.test.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('hardhat'); 2 | const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); 3 | 4 | const { DEFAULT_ADMIN_ROLE, shouldBehaveLikeAccessControl } = require('./AccessControl.behavior'); 5 | 6 | async function fixture() { 7 | const [defaultAdmin, ...accounts] = await ethers.getSigners(); 8 | const mock = await ethers.deployContract('$AccessControl'); 9 | await mock.$_grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin); 10 | return { mock, defaultAdmin, accounts }; 11 | } 12 | 13 | describe('AccessControl', function () { 14 | beforeEach(async function () { 15 | Object.assign(this, await loadFixture(fixture)); 16 | }); 17 | 18 | shouldBehaveLikeAccessControl(); 19 | }); 20 | -------------------------------------------------------------------------------- /test/access/extensions/AccessControlDefaultAdminRules.test.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('hardhat'); 2 | const { expect } = require('chai'); 3 | const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); 4 | 5 | const time = require('../../helpers/time'); 6 | 7 | const { 8 | shouldBehaveLikeAccessControl, 9 | shouldBehaveLikeAccessControlDefaultAdminRules, 10 | } = require('../AccessControl.behavior'); 11 | 12 | async function fixture() { 13 | const delay = time.duration.hours(10); 14 | const [defaultAdmin, ...accounts] = await ethers.getSigners(); 15 | const mock = await ethers.deployContract('$AccessControlDefaultAdminRules', [delay, defaultAdmin]); 16 | return { mock, defaultAdmin, delay, accounts }; 17 | } 18 | 19 | describe('AccessControlDefaultAdminRules', function () { 20 | beforeEach(async function () { 21 | Object.assign(this, await loadFixture(fixture)); 22 | }); 23 | 24 | it('initial admin not zero', async function () { 25 | await expect(ethers.deployContract('$AccessControlDefaultAdminRules', [this.delay, ethers.ZeroAddress])) 26 | .to.be.revertedWithCustomError(this.mock, 'AccessControlInvalidDefaultAdmin') 27 | .withArgs(ethers.ZeroAddress); 28 | }); 29 | 30 | shouldBehaveLikeAccessControl(); 31 | shouldBehaveLikeAccessControlDefaultAdminRules(); 32 | }); 33 | -------------------------------------------------------------------------------- /test/access/extensions/AccessControlEnumerable.test.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('hardhat'); 2 | const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); 3 | 4 | const { 5 | DEFAULT_ADMIN_ROLE, 6 | shouldBehaveLikeAccessControl, 7 | shouldBehaveLikeAccessControlEnumerable, 8 | } = require('../AccessControl.behavior'); 9 | 10 | async function fixture() { 11 | const [defaultAdmin, ...accounts] = await ethers.getSigners(); 12 | const mock = await ethers.deployContract('$AccessControlEnumerable'); 13 | await mock.$_grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin); 14 | return { mock, defaultAdmin, accounts }; 15 | } 16 | 17 | describe('AccessControlEnumerable', function () { 18 | beforeEach(async function () { 19 | Object.assign(this, await loadFixture(fixture)); 20 | }); 21 | 22 | shouldBehaveLikeAccessControl(); 23 | shouldBehaveLikeAccessControlEnumerable(); 24 | }); 25 | -------------------------------------------------------------------------------- /test/bin/EntryPoint070.bytecode: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/test/bin/EntryPoint070.bytecode -------------------------------------------------------------------------------- /test/bin/EntryPoint080.bytecode: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/test/bin/EntryPoint080.bytecode -------------------------------------------------------------------------------- /test/bin/SenderCreator070.abi: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"bytes","name":"initCode","type":"bytes"}],"name":"createSender","outputs":[{"internalType":"address","name":"sender","type":"address"}],"stateMutability":"nonpayable","type":"function"}] -------------------------------------------------------------------------------- /test/bin/SenderCreator070.bytecode: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/test/bin/SenderCreator070.bytecode -------------------------------------------------------------------------------- /test/bin/SenderCreator080.abi: -------------------------------------------------------------------------------- 1 | [{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"opIndex","type":"uint256"},{"internalType":"string","name":"reason","type":"string"},{"internalType":"bytes","name":"inner","type":"bytes"}],"name":"FailedOpWithRevert","type":"error"},{"inputs":[{"internalType":"bytes","name":"initCode","type":"bytes"}],"name":"createSender","outputs":[{"internalType":"address","name":"sender","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"entryPoint","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"bytes","name":"initCallData","type":"bytes"}],"name":"initEip7702Sender","outputs":[],"stateMutability":"nonpayable","type":"function"}] -------------------------------------------------------------------------------- /test/bin/SenderCreator080.bytecode: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/5c79432e4091c20fa5ea057261f0bf528ea70a7c/test/bin/SenderCreator080.bytecode -------------------------------------------------------------------------------- /test/governance/utils/ERC6372.behavior.js: -------------------------------------------------------------------------------- 1 | const { expect } = require('chai'); 2 | const time = require('../../helpers/time'); 3 | 4 | function shouldBehaveLikeERC6372(mode = 'blocknumber') { 5 | describe(`ERC-6372 behavior in ${mode} mode`, function () { 6 | beforeEach(async function () { 7 | this.mock = this.mock ?? this.token ?? this.votes; 8 | }); 9 | 10 | it('should have a correct clock value', async function () { 11 | const currentClock = await this.mock.clock(); 12 | const expectedClock = await time.clock[mode](); 13 | expect(currentClock).to.equal(expectedClock, `Clock mismatch in ${mode} mode`); 14 | }); 15 | 16 | it('should have the correct CLOCK_MODE parameters', async function () { 17 | const clockModeParams = new URLSearchParams(await this.mock.CLOCK_MODE()); 18 | const expectedFromValue = mode === 'blocknumber' ? 'default' : null; 19 | 20 | expect(clockModeParams.get('mode')).to.equal(mode, `Expected mode to be ${mode}`); 21 | expect(clockModeParams.get('from')).to.equal(expectedFromValue, `Expected 'from' to be ${expectedFromValue}`); 22 | }); 23 | }); 24 | } 25 | 26 | module.exports = { 27 | shouldBehaveLikeERC6372, 28 | }; 29 | -------------------------------------------------------------------------------- /test/helpers/account.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('hardhat'); 2 | const { impersonateAccount, setBalance } = require('@nomicfoundation/hardhat-network-helpers'); 3 | 4 | // Hardhat default balance 5 | const DEFAULT_BALANCE = 10000n * ethers.WeiPerEther; 6 | 7 | const impersonate = (account, balance = DEFAULT_BALANCE) => 8 | impersonateAccount(account) 9 | .then(() => setBalance(account, balance)) 10 | .then(() => ethers.getSigner(account)); 11 | 12 | module.exports = { 13 | impersonate, 14 | }; 15 | -------------------------------------------------------------------------------- /test/helpers/constants.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | MAX_UINT32: 2n ** 32n - 1n, 3 | MAX_UINT48: 2n ** 48n - 1n, 4 | MAX_UINT64: 2n ** 64n - 1n, 5 | }; 6 | -------------------------------------------------------------------------------- /test/helpers/deploy.js: -------------------------------------------------------------------------------- 1 | const { artifacts, ethers } = require('hardhat'); 2 | const { setCode } = require('@nomicfoundation/hardhat-network-helpers'); 3 | const { generators } = require('./random'); 4 | 5 | const forceDeployCode = (name, address = generators.address(), runner = ethers.provider) => 6 | artifacts 7 | .readArtifact(name) 8 | .then(({ abi, deployedBytecode }) => 9 | setCode(address, deployedBytecode).then(() => new ethers.Contract(address, abi, runner)), 10 | ); 11 | 12 | module.exports = { 13 | forceDeployCode, 14 | }; 15 | -------------------------------------------------------------------------------- /test/helpers/eip712.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('hardhat'); 2 | const types = require('./eip712-types'); 3 | 4 | async function getDomain(contract) { 5 | const { fields, name, version, chainId, verifyingContract, salt, extensions } = await contract.eip712Domain(); 6 | 7 | if (extensions.length > 0) { 8 | throw Error('Extensions not implemented'); 9 | } 10 | 11 | const domain = { 12 | name, 13 | version, 14 | chainId, 15 | verifyingContract, 16 | salt, 17 | }; 18 | 19 | for (const [i, { name }] of types.EIP712Domain.entries()) { 20 | if (!(fields & (1 << i))) { 21 | delete domain[name]; 22 | } 23 | } 24 | 25 | return domain; 26 | } 27 | 28 | function domainType(domain) { 29 | return types.EIP712Domain.filter(({ name }) => domain[name] !== undefined); 30 | } 31 | 32 | function hashTypedData(domain, structHash) { 33 | return ethers.solidityPackedKeccak256( 34 | ['bytes', 'bytes32', 'bytes32'], 35 | ['0x1901', ethers.TypedDataEncoder.hashDomain(domain), structHash], 36 | ); 37 | } 38 | 39 | module.exports = { 40 | getDomain, 41 | domainType, 42 | domainSeparator: ethers.TypedDataEncoder.hashDomain, 43 | hashTypedData, 44 | ...types, 45 | }; 46 | -------------------------------------------------------------------------------- /test/helpers/enums.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('ethers'); 2 | 3 | const Enum = (...options) => Object.fromEntries(options.map((key, i) => [key, BigInt(i)])); 4 | const EnumTyped = (...options) => Object.fromEntries(options.map((key, i) => [key, ethers.Typed.uint8(i)])); 5 | 6 | module.exports = { 7 | Enum, 8 | EnumTyped, 9 | ProposalState: Enum('Pending', 'Active', 'Canceled', 'Defeated', 'Succeeded', 'Queued', 'Expired', 'Executed'), 10 | VoteType: Object.assign(Enum('Against', 'For', 'Abstain'), { Parameters: 255n }), 11 | Rounding: EnumTyped('Floor', 'Ceil', 'Trunc', 'Expand'), 12 | OperationState: Enum('Unset', 'Waiting', 'Ready', 'Done'), 13 | RevertType: EnumTyped('None', 'RevertWithoutMessage', 'RevertWithMessage', 'RevertWithCustomError', 'Panic'), 14 | }; 15 | -------------------------------------------------------------------------------- /test/helpers/math.js: -------------------------------------------------------------------------------- 1 | // Array of number or bigint 2 | const max = (...values) => values.slice(1).reduce((x, y) => (x > y ? x : y), values.at(0)); 3 | const min = (...values) => values.slice(1).reduce((x, y) => (x < y ? x : y), values.at(0)); 4 | const sum = (...values) => values.slice(1).reduce((x, y) => x + y, values.at(0)); 5 | 6 | // Computes modexp without BigInt overflow for large numbers 7 | function modExp(b, e, m) { 8 | let result = 1n; 9 | 10 | // If e is a power of two, modexp can be calculated as: 11 | // for (let result = b, i = 0; i < log2(e); i++) result = modexp(result, 2, m) 12 | // 13 | // Given any natural number can be written in terms of powers of 2 (i.e. binary) 14 | // then modexp can be calculated for any e, by multiplying b**i for all i where 15 | // binary(e)[i] is 1 (i.e. a power of two). 16 | for (let base = b % m; e > 0n; base = base ** 2n % m) { 17 | // Least significant bit is 1 18 | if (e % 2n == 1n) { 19 | result = (result * base) % m; 20 | } 21 | 22 | e /= 2n; // Binary pop 23 | } 24 | 25 | return result; 26 | } 27 | 28 | module.exports = { 29 | min, 30 | max, 31 | sum, 32 | modExp, 33 | }; 34 | -------------------------------------------------------------------------------- /test/helpers/methods.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('hardhat'); 2 | 3 | const selector = signature => ethers.FunctionFragment.from(signature).selector; 4 | 5 | const interfaceId = signatures => 6 | ethers.toBeHex( 7 | signatures.reduce((acc, signature) => acc ^ ethers.toBigInt(selector(signature)), 0n), 8 | 4, 9 | ); 10 | 11 | module.exports = { 12 | selector, 13 | interfaceId, 14 | }; 15 | -------------------------------------------------------------------------------- /test/helpers/precompiles.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ecRecover: '0x0000000000000000000000000000000000000001', 3 | SHA2_256: '0x0000000000000000000000000000000000000002', 4 | RIPEMD_160: '0x0000000000000000000000000000000000000003', 5 | identity: '0x0000000000000000000000000000000000000004', 6 | modexp: '0x0000000000000000000000000000000000000005', 7 | ecAdd: '0x0000000000000000000000000000000000000006', 8 | ecMul: '0x0000000000000000000000000000000000000007', 9 | ecPairing: '0x0000000000000000000000000000000000000008', 10 | blake2f: '0x0000000000000000000000000000000000000009', 11 | pointEvaluation: '0x000000000000000000000000000000000000000a', 12 | }; 13 | -------------------------------------------------------------------------------- /test/helpers/random.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('hardhat'); 2 | 3 | const generators = { 4 | address: () => ethers.Wallet.createRandom().address, 5 | bytes32: () => ethers.hexlify(ethers.randomBytes(32)), 6 | uint256: () => ethers.toBigInt(ethers.randomBytes(32)), 7 | int256: () => ethers.toBigInt(ethers.randomBytes(32)) + ethers.MinInt256, 8 | bytes: (length = 32) => ethers.hexlify(ethers.randomBytes(length)), 9 | string: () => ethers.uuidV4(ethers.randomBytes(32)), 10 | }; 11 | 12 | generators.address.zero = ethers.ZeroAddress; 13 | generators.bytes32.zero = ethers.ZeroHash; 14 | generators.uint256.zero = 0n; 15 | generators.int256.zero = 0n; 16 | generators.bytes.zero = '0x'; 17 | generators.string.zero = ''; 18 | 19 | // alias hexBytes -> bytes 20 | generators.hexBytes = generators.bytes; 21 | 22 | module.exports = { 23 | generators, 24 | }; 25 | -------------------------------------------------------------------------------- /test/helpers/strings.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // Capitalize the first char of a string 3 | // Example: capitalize('uint256') → 'Uint256' 4 | capitalize: str => str.charAt(0).toUpperCase() + str.slice(1), 5 | }; 6 | -------------------------------------------------------------------------------- /test/helpers/time.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('hardhat'); 2 | const { time, mine, mineUpTo } = require('@nomicfoundation/hardhat-network-helpers'); 3 | const { mapValues } = require('./iterate'); 4 | 5 | const clock = { 6 | blocknumber: () => time.latestBlock().then(ethers.toBigInt), 7 | timestamp: () => time.latest().then(ethers.toBigInt), 8 | }; 9 | const clockFromReceipt = { 10 | blocknumber: receipt => Promise.resolve(receipt).then(({ blockNumber }) => ethers.toBigInt(blockNumber)), 11 | timestamp: receipt => 12 | Promise.resolve(receipt) 13 | .then(({ blockNumber }) => ethers.provider.getBlock(blockNumber)) 14 | .then(({ timestamp }) => ethers.toBigInt(timestamp)), 15 | }; 16 | const increaseBy = { 17 | blockNumber: mine, 18 | timestamp: (delay, mine = true) => 19 | time.latest().then(clock => increaseTo.timestamp(clock + ethers.toNumber(delay), mine)), 20 | }; 21 | const increaseTo = { 22 | blocknumber: mineUpTo, 23 | timestamp: (to, mine = true) => (mine ? time.increaseTo(to) : time.setNextBlockTimestamp(to)), 24 | }; 25 | const duration = mapValues(time.duration, fn => n => ethers.toBigInt(fn(ethers.toNumber(n)))); 26 | 27 | module.exports = { 28 | clock, 29 | clockFromReceipt, 30 | increaseBy, 31 | increaseTo, 32 | duration, 33 | }; 34 | -------------------------------------------------------------------------------- /test/helpers/txpool.js: -------------------------------------------------------------------------------- 1 | const { network } = require('hardhat'); 2 | const { expect } = require('chai'); 3 | const { mine } = require('@nomicfoundation/hardhat-network-helpers'); 4 | 5 | const { unique } = require('./iterate'); 6 | 7 | async function batchInBlock(txs) { 8 | try { 9 | // disable auto-mining 10 | await network.provider.send('evm_setAutomine', [false]); 11 | // send all transactions 12 | const responses = await Promise.all(txs.map(fn => fn())); 13 | // mine one block 14 | await mine(); 15 | // fetch receipts 16 | const receipts = await Promise.all(responses.map(response => response.wait())); 17 | // Sanity check, all tx should be in the same block 18 | expect(unique(receipts.map(receipt => receipt.blockNumber))).to.have.lengthOf(1); 19 | // return responses 20 | return receipts; 21 | } finally { 22 | // enable auto-mining 23 | await network.provider.send('evm_setAutomine', [true]); 24 | } 25 | } 26 | 27 | module.exports = { 28 | batchInBlock, 29 | }; 30 | -------------------------------------------------------------------------------- /test/proxy/ERC1967/ERC1967Proxy.test.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('hardhat'); 2 | 3 | const shouldBehaveLikeProxy = require('../Proxy.behaviour'); 4 | const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); 5 | 6 | const fixture = async () => { 7 | const [nonContractAddress] = await ethers.getSigners(); 8 | 9 | const implementation = await ethers.deployContract('DummyImplementation'); 10 | 11 | const createProxy = (implementation, initData, opts) => 12 | ethers.deployContract('ERC1967Proxy', [implementation, initData], opts); 13 | 14 | return { nonContractAddress, implementation, createProxy }; 15 | }; 16 | 17 | describe('ERC1967Proxy', function () { 18 | beforeEach(async function () { 19 | Object.assign(this, await loadFixture(fixture)); 20 | }); 21 | 22 | shouldBehaveLikeProxy(); 23 | }); 24 | -------------------------------------------------------------------------------- /test/proxy/transparent/TransparentUpgradeableProxy.test.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('hardhat'); 2 | const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); 3 | 4 | const shouldBehaveLikeProxy = require('../Proxy.behaviour'); 5 | const shouldBehaveLikeTransparentUpgradeableProxy = require('./TransparentUpgradeableProxy.behaviour'); 6 | 7 | async function fixture() { 8 | const [owner, other, ...accounts] = await ethers.getSigners(); 9 | 10 | const implementation = await ethers.deployContract('DummyImplementation'); 11 | 12 | const createProxy = function (logic, initData, opts = undefined) { 13 | return ethers.deployContract('TransparentUpgradeableProxy', [logic, owner, initData], opts); 14 | }; 15 | 16 | return { nonContractAddress: owner, owner, other, accounts, implementation, createProxy }; 17 | } 18 | 19 | describe('TransparentUpgradeableProxy', function () { 20 | beforeEach(async function () { 21 | Object.assign(this, await loadFixture(fixture)); 22 | }); 23 | 24 | shouldBehaveLikeProxy(); 25 | 26 | // createProxy, owner, otherAccounts 27 | shouldBehaveLikeTransparentUpgradeableProxy(); 28 | }); 29 | -------------------------------------------------------------------------------- /test/sanity.test.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('hardhat'); 2 | const { expect } = require('chai'); 3 | const { loadFixture, mine } = require('@nomicfoundation/hardhat-network-helpers'); 4 | 5 | async function fixture() { 6 | return {}; 7 | } 8 | 9 | describe('Environment sanity', function () { 10 | beforeEach(async function () { 11 | Object.assign(this, await loadFixture(fixture)); 12 | }); 13 | 14 | describe('snapshot', function () { 15 | let blockNumberBefore; 16 | 17 | it('cache and mine', async function () { 18 | blockNumberBefore = await ethers.provider.getBlockNumber(); 19 | await mine(); 20 | expect(await ethers.provider.getBlockNumber()).to.equal(blockNumberBefore + 1); 21 | }); 22 | 23 | it('check snapshot', async function () { 24 | expect(await ethers.provider.getBlockNumber()).to.equal(blockNumberBefore); 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/token/ERC721/ERC721.test.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('hardhat'); 2 | const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); 3 | 4 | const { shouldBehaveLikeERC721, shouldBehaveLikeERC721Metadata } = require('./ERC721.behavior'); 5 | 6 | const name = 'Non Fungible Token'; 7 | const symbol = 'NFT'; 8 | 9 | async function fixture() { 10 | return { 11 | accounts: await ethers.getSigners(), 12 | token: await ethers.deployContract('$ERC721', [name, symbol]), 13 | }; 14 | } 15 | 16 | describe('ERC721', function () { 17 | beforeEach(async function () { 18 | Object.assign(this, await loadFixture(fixture)); 19 | }); 20 | 21 | shouldBehaveLikeERC721(); 22 | shouldBehaveLikeERC721Metadata(name, symbol); 23 | }); 24 | -------------------------------------------------------------------------------- /test/token/ERC721/ERC721Enumerable.test.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('hardhat'); 2 | const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); 3 | 4 | const { 5 | shouldBehaveLikeERC721, 6 | shouldBehaveLikeERC721Metadata, 7 | shouldBehaveLikeERC721Enumerable, 8 | } = require('./ERC721.behavior'); 9 | 10 | const name = 'Non Fungible Token'; 11 | const symbol = 'NFT'; 12 | 13 | async function fixture() { 14 | return { 15 | accounts: await ethers.getSigners(), 16 | token: await ethers.deployContract('$ERC721Enumerable', [name, symbol]), 17 | }; 18 | } 19 | 20 | describe('ERC721', function () { 21 | beforeEach(async function () { 22 | Object.assign(this, await loadFixture(fixture)); 23 | }); 24 | 25 | shouldBehaveLikeERC721(); 26 | shouldBehaveLikeERC721Metadata(name, symbol); 27 | shouldBehaveLikeERC721Enumerable(); 28 | }); 29 | -------------------------------------------------------------------------------- /test/token/ERC721/utils/ERC721Holder.test.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('hardhat'); 2 | const { expect } = require('chai'); 3 | 4 | const name = 'Non Fungible Token'; 5 | const symbol = 'NFT'; 6 | const tokenId = 1n; 7 | 8 | describe('ERC721Holder', function () { 9 | it('receives an ERC721 token', async function () { 10 | const [owner] = await ethers.getSigners(); 11 | 12 | const token = await ethers.deployContract('$ERC721', [name, symbol]); 13 | await token.$_mint(owner, tokenId); 14 | 15 | const receiver = await ethers.deployContract('$ERC721Holder'); 16 | await token.connect(owner).safeTransferFrom(owner, receiver, tokenId); 17 | 18 | expect(await token.ownerOf(tokenId)).to.equal(receiver); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/utils/Arrays.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {Test} from "forge-std/Test.sol"; 6 | import {SymTest} from "halmos-cheatcodes/SymTest.sol"; 7 | import {Arrays} from "@openzeppelin/contracts/utils/Arrays.sol"; 8 | 9 | contract ArraysTest is Test, SymTest { 10 | function testSort(uint256[] memory values) public pure { 11 | Arrays.sort(values); 12 | _assertSort(values); 13 | } 14 | 15 | function symbolicSort() public pure { 16 | uint256[] memory values = new uint256[](3); 17 | for (uint256 i = 0; i < 3; i++) { 18 | values[i] = svm.createUint256("arrayElement"); 19 | } 20 | Arrays.sort(values); 21 | _assertSort(values); 22 | } 23 | 24 | /// Asserts 25 | 26 | function _assertSort(uint256[] memory values) internal pure { 27 | for (uint256 i = 1; i < values.length; ++i) { 28 | assertLe(values[i - 1], values[i]); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test/utils/Base64.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {Test} from "forge-std/Test.sol"; 6 | import {Base64} from "@openzeppelin/contracts/utils/Base64.sol"; 7 | 8 | contract Base64Test is Test { 9 | function testEncode(bytes memory input) external pure { 10 | assertEq(Base64.encode(input), vm.toBase64(input)); 11 | } 12 | 13 | function testEncodeURL(bytes memory input) external pure { 14 | assertEq(Base64.encodeURL(input), _removePadding(vm.toBase64URL(input))); 15 | } 16 | 17 | function _removePadding(string memory inputStr) internal pure returns (string memory) { 18 | bytes memory input = bytes(inputStr); 19 | bytes memory output; 20 | 21 | for (uint256 i = 0; i < input.length; ++i) { 22 | if (input[input.length - i - 1] != 0x3d) { 23 | output = new bytes(input.length - i); 24 | break; 25 | } 26 | } 27 | 28 | for (uint256 i = 0; i < output.length; ++i) { 29 | output[i] = input[i]; 30 | } 31 | 32 | return string(output); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /test/utils/Calldata.test.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('hardhat'); 2 | const { expect } = require('chai'); 3 | const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); 4 | 5 | async function fixture() { 6 | const mock = await ethers.deployContract('$Calldata'); 7 | return { mock }; 8 | } 9 | 10 | describe('Calldata utilities', function () { 11 | beforeEach(async function () { 12 | Object.assign(this, await loadFixture(fixture)); 13 | }); 14 | 15 | it('emptyBytes', async function () { 16 | await expect(this.mock.$emptyBytes()).to.eventually.equal('0x'); 17 | }); 18 | 19 | it('emptyString', async function () { 20 | await expect(this.mock.$emptyString()).to.eventually.equal(''); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /test/utils/Context.test.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('hardhat'); 2 | const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); 3 | 4 | const { shouldBehaveLikeRegularContext } = require('./Context.behavior'); 5 | 6 | async function fixture() { 7 | const [sender] = await ethers.getSigners(); 8 | const context = await ethers.deployContract('ContextMock', []); 9 | return { sender, context }; 10 | } 11 | 12 | describe('Context', function () { 13 | beforeEach(async function () { 14 | Object.assign(this, await loadFixture(fixture)); 15 | }); 16 | 17 | shouldBehaveLikeRegularContext(); 18 | }); 19 | -------------------------------------------------------------------------------- /test/utils/Create2.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import {Test} from "forge-std/Test.sol"; 6 | import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; 7 | 8 | contract Create2Test is Test { 9 | function testSymbolicComputeAddressSpillage(bytes32 salt, bytes32 bytecodeHash, address deployer) public pure { 10 | address predicted = Create2.computeAddress(salt, bytecodeHash, deployer); 11 | bytes32 spillage; 12 | assembly ("memory-safe") { 13 | spillage := and(predicted, 0xffffffffffffffffffffffff0000000000000000000000000000000000000000) 14 | } 15 | assertEq(spillage, bytes32(0)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/utils/Nonces.test.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('hardhat'); 2 | const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); 3 | const { shouldBehaveLikeNonces } = require('./Nonces.behavior'); 4 | 5 | async function fixture() { 6 | const mock = await ethers.deployContract('$Nonces'); 7 | return { mock }; 8 | } 9 | 10 | describe('Nonces', function () { 11 | beforeEach(async function () { 12 | Object.assign(this, await loadFixture(fixture)); 13 | }); 14 | 15 | shouldBehaveLikeNonces(); 16 | }); 17 | -------------------------------------------------------------------------------- /test/utils/NoncesKeyed.test.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('hardhat'); 2 | const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); 3 | const { shouldBehaveLikeNonces, shouldBehaveLikeNoncesKeyed } = require('./Nonces.behavior'); 4 | 5 | async function fixture() { 6 | const mock = await ethers.deployContract('$NoncesKeyed'); 7 | return { mock }; 8 | } 9 | 10 | describe('NoncesKeyed', function () { 11 | beforeEach(async function () { 12 | Object.assign(this, await loadFixture(fixture)); 13 | }); 14 | 15 | shouldBehaveLikeNonces(); 16 | shouldBehaveLikeNoncesKeyed(); 17 | }); 18 | -------------------------------------------------------------------------------- /test/utils/cryptography/RSA.helper.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | 4 | module.exports = function* parse(file) { 5 | const cache = {}; 6 | const data = fs.readFileSync(path.resolve(__dirname, file), 'utf8'); 7 | for (const line of data.split('\r\n')) { 8 | const groups = line.match(/^(?\w+) = (?\w+)(?.*)$/)?.groups; 9 | if (groups) { 10 | const { key, value, extra } = groups; 11 | cache[key] = value; 12 | if (groups.key === 'Result') { 13 | yield Object.assign({ extra: extra.trim() }, cache); 14 | } 15 | } 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /test/utils/introspection/ERC165.test.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require('hardhat'); 2 | const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); 3 | 4 | const { shouldSupportInterfaces } = require('./SupportsInterface.behavior'); 5 | 6 | async function fixture() { 7 | return { 8 | mock: await ethers.deployContract('$ERC165'), 9 | }; 10 | } 11 | 12 | describe('ERC165', function () { 13 | beforeEach(async function () { 14 | Object.assign(this, await loadFixture(fixture)); 15 | }); 16 | 17 | shouldSupportInterfaces(); 18 | }); 19 | --------------------------------------------------------------------------------