web3gbit-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/--broadcast +0 -0
- package/--private-key +0 -0
- package/--rpc-url +0 -0
- package/.github/workflows/test.yml +38 -0
- package/.gitmodules +3 -0
- package/GbitToken_flat.sol +2 -0
- package/GbitToken_flat.solnpx +0 -0
- package/README.md +72 -0
- package/admin-cli.js +413 -0
- package/cache/solidity-files-cache.json +1 -0
- package/foundry.lock +8 -0
- package/foundry.toml +6 -0
- package/lib/forge-std/.gitattributes +1 -0
- package/lib/forge-std/.github/CODEOWNERS +1 -0
- package/lib/forge-std/.github/dependabot.yml +6 -0
- package/lib/forge-std/.github/workflows/ci.yml +125 -0
- package/lib/forge-std/.github/workflows/sync.yml +36 -0
- package/lib/forge-std/CONTRIBUTING.md +193 -0
- package/lib/forge-std/LICENSE-APACHE +203 -0
- package/lib/forge-std/LICENSE-MIT +25 -0
- package/lib/forge-std/README.md +268 -0
- package/lib/forge-std/RELEASE_CHECKLIST.md +12 -0
- package/lib/forge-std/foundry.toml +18 -0
- package/lib/forge-std/package.json +16 -0
- package/lib/forge-std/scripts/vm.py +636 -0
- package/lib/forge-std/src/Base.sol +48 -0
- package/lib/forge-std/src/Config.sol +60 -0
- package/lib/forge-std/src/LibVariable.sol +477 -0
- package/lib/forge-std/src/Script.sol +28 -0
- package/lib/forge-std/src/StdAssertions.sol +779 -0
- package/lib/forge-std/src/StdChains.sol +295 -0
- package/lib/forge-std/src/StdCheats.sol +825 -0
- package/lib/forge-std/src/StdConfig.sol +632 -0
- package/lib/forge-std/src/StdConstants.sol +30 -0
- package/lib/forge-std/src/StdError.sol +15 -0
- package/lib/forge-std/src/StdInvariant.sol +120 -0
- package/lib/forge-std/src/StdJson.sol +275 -0
- package/lib/forge-std/src/StdMath.sol +47 -0
- package/lib/forge-std/src/StdStorage.sol +475 -0
- package/lib/forge-std/src/StdStyle.sol +333 -0
- package/lib/forge-std/src/StdToml.sol +275 -0
- package/lib/forge-std/src/StdUtils.sol +200 -0
- package/lib/forge-std/src/Test.sol +32 -0
- package/lib/forge-std/src/Vm.sol +2500 -0
- package/lib/forge-std/src/console.sol +1551 -0
- package/lib/forge-std/src/console2.sol +4 -0
- package/lib/forge-std/src/interfaces/IERC1155.sol +105 -0
- package/lib/forge-std/src/interfaces/IERC165.sol +12 -0
- package/lib/forge-std/src/interfaces/IERC20.sol +43 -0
- package/lib/forge-std/src/interfaces/IERC4626.sol +190 -0
- package/lib/forge-std/src/interfaces/IERC6909.sol +72 -0
- package/lib/forge-std/src/interfaces/IERC721.sol +164 -0
- package/lib/forge-std/src/interfaces/IERC7540.sol +144 -0
- package/lib/forge-std/src/interfaces/IERC7575.sol +241 -0
- package/lib/forge-std/src/interfaces/IMulticall3.sol +68 -0
- package/lib/forge-std/src/safeconsole.sol +13248 -0
- package/lib/forge-std/test/CommonBase.t.sol +44 -0
- package/lib/forge-std/test/Config.t.sol +381 -0
- package/lib/forge-std/test/LibVariable.t.sol +452 -0
- package/lib/forge-std/test/StdAssertions.t.sol +141 -0
- package/lib/forge-std/test/StdChains.t.sol +227 -0
- package/lib/forge-std/test/StdCheats.t.sol +638 -0
- package/lib/forge-std/test/StdConstants.t.sol +38 -0
- package/lib/forge-std/test/StdError.t.sol +119 -0
- package/lib/forge-std/test/StdJson.t.sol +49 -0
- package/lib/forge-std/test/StdMath.t.sol +202 -0
- package/lib/forge-std/test/StdStorage.t.sol +485 -0
- package/lib/forge-std/test/StdStyle.t.sol +110 -0
- package/lib/forge-std/test/StdToml.t.sol +49 -0
- package/lib/forge-std/test/StdUtils.t.sol +342 -0
- package/lib/forge-std/test/Vm.t.sol +18 -0
- package/lib/forge-std/test/compilation/CompilationScript.sol +8 -0
- package/lib/forge-std/test/compilation/CompilationScriptBase.sol +8 -0
- package/lib/forge-std/test/compilation/CompilationTest.sol +8 -0
- package/lib/forge-std/test/compilation/CompilationTestBase.sol +8 -0
- package/lib/forge-std/test/fixtures/broadcast.log.json +187 -0
- package/lib/forge-std/test/fixtures/config.toml +81 -0
- package/lib/forge-std/test/fixtures/test.json +8 -0
- package/lib/forge-std/test/fixtures/test.toml +6 -0
- package/lib/openzeppelin-contracts/.changeset/blue-mirrors-agree.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/bright-webs-create.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/clean-worlds-end.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/config.json +12 -0
- package/lib/openzeppelin-contracts/.changeset/curly-pandas-flow.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/flat-ideas-count.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/fluffy-facts-brake.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/forty-ads-design.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/full-emus-hear.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/fuzzy-lizards-do.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/grumpy-cats-brake.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/khaki-crews-join.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/new-socks-deny.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/shaky-phones-mix.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/social-tools-sniff.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/spotty-plums-brush.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/stale-lizards-cheat.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/swift-planets-juggle.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/tame-monkeys-make.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/tender-pans-yawn.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/thick-banks-relate.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/vast-worlds-pull.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/whole-turkeys-swim.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/yellow-clowns-mate.md +5 -0
- package/lib/openzeppelin-contracts/.changeset/young-corners-help.md +5 -0
- package/lib/openzeppelin-contracts/.codecov.yml +16 -0
- package/lib/openzeppelin-contracts/.editorconfig +21 -0
- package/lib/openzeppelin-contracts/.gitattributes +3 -0
- package/lib/openzeppelin-contracts/.github/CODEOWNERS +10 -0
- package/lib/openzeppelin-contracts/.github/ISSUE_TEMPLATE/bug_report.md +21 -0
- package/lib/openzeppelin-contracts/.github/ISSUE_TEMPLATE/config.yml +4 -0
- package/lib/openzeppelin-contracts/.github/ISSUE_TEMPLATE/feature_request.md +14 -0
- package/lib/openzeppelin-contracts/.github/PULL_REQUEST_TEMPLATE.md +20 -0
- package/lib/openzeppelin-contracts/.github/actions/gas-compare/action.yml +51 -0
- package/lib/openzeppelin-contracts/.github/actions/setup/action.yml +108 -0
- package/lib/openzeppelin-contracts/.github/actions/storage-layout/action.yml +57 -0
- package/lib/openzeppelin-contracts/.github/workflows/actionlint.yml +18 -0
- package/lib/openzeppelin-contracts/.github/workflows/changeset.yml +28 -0
- package/lib/openzeppelin-contracts/.github/workflows/checks.yml +132 -0
- package/lib/openzeppelin-contracts/.github/workflows/docs.yml +19 -0
- package/lib/openzeppelin-contracts/.github/workflows/formal-verification.yml +63 -0
- package/lib/openzeppelin-contracts/.github/workflows/release-cycle.yml +212 -0
- package/lib/openzeppelin-contracts/.github/workflows/release-upgradeable.yml +95 -0
- package/lib/openzeppelin-contracts/.github/workflows/upgradeable.yml +35 -0
- package/lib/openzeppelin-contracts/.gitmodules +10 -0
- package/lib/openzeppelin-contracts/.husky/pre-commit +2 -0
- package/lib/openzeppelin-contracts/.mocharc.js +4 -0
- package/lib/openzeppelin-contracts/.prettierrc +15 -0
- package/lib/openzeppelin-contracts/.solcover.js +21 -0
- package/lib/openzeppelin-contracts/CHANGELOG.md +1364 -0
- package/lib/openzeppelin-contracts/CODE_OF_CONDUCT.md +73 -0
- package/lib/openzeppelin-contracts/CONTRIBUTING.md +36 -0
- package/lib/openzeppelin-contracts/FUNDING.json +10 -0
- package/lib/openzeppelin-contracts/GUIDELINES.md +170 -0
- package/lib/openzeppelin-contracts/LICENSE +22 -0
- package/lib/openzeppelin-contracts/README.md +122 -0
- package/lib/openzeppelin-contracts/RELEASING.md +45 -0
- package/lib/openzeppelin-contracts/SECURITY.md +43 -0
- package/lib/openzeppelin-contracts/audits/2017-03.md +292 -0
- package/lib/openzeppelin-contracts/audits/2018-10.pdf +0 -0
- package/lib/openzeppelin-contracts/audits/2022-10-Checkpoints.pdf +0 -0
- package/lib/openzeppelin-contracts/audits/2022-10-ERC4626.pdf +0 -0
- package/lib/openzeppelin-contracts/audits/2023-05-v4.9.pdf +0 -0
- package/lib/openzeppelin-contracts/audits/2023-10-v5.0.pdf +0 -0
- package/lib/openzeppelin-contracts/audits/2024-10-v5.1.pdf +0 -0
- package/lib/openzeppelin-contracts/audits/2024-12-v5.2.pdf +0 -0
- package/lib/openzeppelin-contracts/audits/2025-04-v5.3.pdf +0 -0
- package/lib/openzeppelin-contracts/audits/2025-07-v5.4.pdf +0 -0
- package/lib/openzeppelin-contracts/audits/2025-10-v5.5.pdf +0 -0
- package/lib/openzeppelin-contracts/audits/README.md +22 -0
- package/lib/openzeppelin-contracts/contracts/access/AccessControl.sol +207 -0
- package/lib/openzeppelin-contracts/contracts/access/IAccessControl.sol +98 -0
- package/lib/openzeppelin-contracts/contracts/access/Ownable.sol +100 -0
- package/lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol +67 -0
- package/lib/openzeppelin-contracts/contracts/access/README.adoc +45 -0
- package/lib/openzeppelin-contracts/contracts/access/extensions/AccessControlDefaultAdminRules.sol +372 -0
- package/lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol +81 -0
- package/lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlDefaultAdminRules.sol +192 -0
- package/lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol +31 -0
- package/lib/openzeppelin-contracts/contracts/access/manager/AccessManaged.sol +112 -0
- package/lib/openzeppelin-contracts/contracts/access/manager/AccessManager.sol +741 -0
- package/lib/openzeppelin-contracts/contracts/access/manager/AuthorityUtils.sol +36 -0
- package/lib/openzeppelin-contracts/contracts/access/manager/IAccessManaged.sol +32 -0
- package/lib/openzeppelin-contracts/contracts/access/manager/IAccessManager.sol +403 -0
- package/lib/openzeppelin-contracts/contracts/access/manager/IAuthority.sol +14 -0
- package/lib/openzeppelin-contracts/contracts/account/Account.sol +151 -0
- package/lib/openzeppelin-contracts/contracts/account/README.adoc +30 -0
- package/lib/openzeppelin-contracts/contracts/account/extensions/draft-AccountERC7579.sol +420 -0
- package/lib/openzeppelin-contracts/contracts/account/extensions/draft-AccountERC7579Hooked.sol +107 -0
- package/lib/openzeppelin-contracts/contracts/account/extensions/draft-ERC7821.sol +70 -0
- package/lib/openzeppelin-contracts/contracts/account/utils/EIP7702Utils.sol +21 -0
- package/lib/openzeppelin-contracts/contracts/account/utils/draft-ERC4337Utils.sol +279 -0
- package/lib/openzeppelin-contracts/contracts/account/utils/draft-ERC7579Utils.sol +280 -0
- package/lib/openzeppelin-contracts/contracts/crosschain/CrosschainLinked.sol +108 -0
- package/lib/openzeppelin-contracts/contracts/crosschain/ERC7786Recipient.sol +70 -0
- package/lib/openzeppelin-contracts/contracts/crosschain/README.adoc +29 -0
- package/lib/openzeppelin-contracts/contracts/crosschain/bridges/BridgeERC20.sol +36 -0
- package/lib/openzeppelin-contracts/contracts/crosschain/bridges/BridgeERC20Core.sol +79 -0
- package/lib/openzeppelin-contracts/contracts/crosschain/bridges/BridgeERC7802.sol +33 -0
- package/lib/openzeppelin-contracts/contracts/finance/README.adoc +14 -0
- package/lib/openzeppelin-contracts/contracts/finance/VestingWallet.sol +160 -0
- package/lib/openzeppelin-contracts/contracts/finance/VestingWalletCliff.sol +54 -0
- package/lib/openzeppelin-contracts/contracts/governance/Governor.sol +819 -0
- package/lib/openzeppelin-contracts/contracts/governance/IGovernor.sol +454 -0
- package/lib/openzeppelin-contracts/contracts/governance/README.adoc +197 -0
- package/lib/openzeppelin-contracts/contracts/governance/TimelockController.sol +470 -0
- package/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorCountingFractional.sol +190 -0
- package/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorCountingOverridable.sol +222 -0
- package/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorCountingSimple.sol +96 -0
- package/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorNoncesKeyed.sol +91 -0
- package/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorPreventLateQuorum.sol +92 -0
- package/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorProposalGuardian.sol +59 -0
- package/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorSequentialProposalId.sol +75 -0
- package/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorSettings.sol +106 -0
- package/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorStorage.sol +134 -0
- package/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorSuperQuorum.sol +59 -0
- package/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockAccess.sol +346 -0
- package/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol +165 -0
- package/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockControl.sol +167 -0
- package/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorVotes.sol +63 -0
- package/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorVotesQuorumFraction.sol +113 -0
- package/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorVotesSuperQuorumFraction.sol +135 -0
- package/lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol +60 -0
- package/lib/openzeppelin-contracts/contracts/governance/utils/Votes.sol +253 -0
- package/lib/openzeppelin-contracts/contracts/governance/utils/VotesExtended.sol +85 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC1155.sol +6 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC1155MetadataURI.sol +6 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC1155Receiver.sol +6 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC1271.sol +17 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol +86 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC1363Receiver.sol +32 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC1363Spender.sol +26 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol +6 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC1820Implementer.sol +20 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC1820Registry.sol +112 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC1967.sol +24 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol +6 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC20Metadata.sol +6 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC2309.sol +19 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC2612.sol +8 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC2981.sol +26 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC3156.sol +7 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC3156FlashBorrower.sol +27 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC3156FlashLender.sol +41 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol +230 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC4906.sol +20 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC5267.sol +28 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC5313.sol +16 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC5805.sol +9 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC6372.sol +17 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC6909.sol +125 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC721.sol +6 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC721Enumerable.sol +6 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC721Metadata.sol +6 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC721Receiver.sol +6 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC7751.sol +12 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC777.sol +200 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC777Recipient.sol +35 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC777Sender.sol +35 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/IERC7913.sol +18 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/README.adoc +138 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC1822.sol +20 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC4337.sol +255 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol +162 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC7579.sol +227 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC7674.sol +17 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC7786.sol +64 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC7802.sol +32 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC7821.sol +44 -0
- package/lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol +90 -0
- package/lib/openzeppelin-contracts/contracts/metatx/ERC2771Forwarder.sol +372 -0
- package/lib/openzeppelin-contracts/contracts/metatx/README.adoc +17 -0
- package/lib/openzeppelin-contracts/contracts/mocks/AccessManagedTarget.sol +34 -0
- package/lib/openzeppelin-contracts/contracts/mocks/AccessManagerMock.sol +20 -0
- package/lib/openzeppelin-contracts/contracts/mocks/ArraysMock.sol +171 -0
- package/lib/openzeppelin-contracts/contracts/mocks/AuthorityMock.sol +69 -0
- package/lib/openzeppelin-contracts/contracts/mocks/Base64Dirty.sol +19 -0
- package/lib/openzeppelin-contracts/contracts/mocks/BatchCaller.sol +20 -0
- package/lib/openzeppelin-contracts/contracts/mocks/CallReceiverMock.sol +106 -0
- package/lib/openzeppelin-contracts/contracts/mocks/ConstructorMock.sol +34 -0
- package/lib/openzeppelin-contracts/contracts/mocks/ContextMock.sol +35 -0
- package/lib/openzeppelin-contracts/contracts/mocks/DummyImplementation.sol +61 -0
- package/lib/openzeppelin-contracts/contracts/mocks/EIP712Verifier.sol +16 -0
- package/lib/openzeppelin-contracts/contracts/mocks/ERC1271WalletMock.sol +24 -0
- package/lib/openzeppelin-contracts/contracts/mocks/ERC165Mock.sol +100 -0
- package/lib/openzeppelin-contracts/contracts/mocks/ERC2771ContextMock.sol +28 -0
- package/lib/openzeppelin-contracts/contracts/mocks/ERC3156FlashBorrowerMock.sol +53 -0
- package/lib/openzeppelin-contracts/contracts/mocks/EtherReceiverMock.sol +17 -0
- package/lib/openzeppelin-contracts/contracts/mocks/InitializableMock.sol +130 -0
- package/lib/openzeppelin-contracts/contracts/mocks/MerkleProofCustomHashMock.sol +62 -0
- package/lib/openzeppelin-contracts/contracts/mocks/MerkleTreeMock.sol +52 -0
- package/lib/openzeppelin-contracts/contracts/mocks/MulticallHelper.sol +23 -0
- package/lib/openzeppelin-contracts/contracts/mocks/MultipleInheritanceInitializableMocks.sol +131 -0
- package/lib/openzeppelin-contracts/contracts/mocks/PausableMock.sol +31 -0
- package/lib/openzeppelin-contracts/contracts/mocks/ReentrancyAttack.sol +17 -0
- package/lib/openzeppelin-contracts/contracts/mocks/ReentrancyMock.sol +59 -0
- package/lib/openzeppelin-contracts/contracts/mocks/ReentrancyTransientMock.sol +59 -0
- package/lib/openzeppelin-contracts/contracts/mocks/RegressionImplementation.sol +61 -0
- package/lib/openzeppelin-contracts/contracts/mocks/SingleInheritanceInitializableMocks.sol +49 -0
- package/lib/openzeppelin-contracts/contracts/mocks/Stateless.sol +62 -0
- package/lib/openzeppelin-contracts/contracts/mocks/StorageSlotMock.sol +87 -0
- package/lib/openzeppelin-contracts/contracts/mocks/TimelockReentrant.sol +26 -0
- package/lib/openzeppelin-contracts/contracts/mocks/TransientSlotMock.sol +61 -0
- package/lib/openzeppelin-contracts/contracts/mocks/UpgradeableBeaconMock.sol +27 -0
- package/lib/openzeppelin-contracts/contracts/mocks/VotesExtendedMock.sol +42 -0
- package/lib/openzeppelin-contracts/contracts/mocks/VotesMock.sol +42 -0
- package/lib/openzeppelin-contracts/contracts/mocks/account/AccountMock.sol +181 -0
- package/lib/openzeppelin-contracts/contracts/mocks/account/modules/ERC7579Mock.sol +128 -0
- package/lib/openzeppelin-contracts/contracts/mocks/account/utils/ERC7579UtilsMock.sol +23 -0
- package/lib/openzeppelin-contracts/contracts/mocks/compound/CompTimelock.sol +174 -0
- package/lib/openzeppelin-contracts/contracts/mocks/crosschain/ERC7786GatewayMock.sol +56 -0
- package/lib/openzeppelin-contracts/contracts/mocks/crosschain/ERC7786RecipientMock.sol +31 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/AccessManagerEnumerable.sol +161 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/ERC20WithAutoMinerReward.sol +22 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/ERC4626Fees.sol +109 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/MyNFT.sol +9 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/access-control/AccessControlERC20MintBase.sol +25 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/access-control/AccessControlERC20MintMissing.sol +24 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/access-control/AccessControlERC20MintOnlyRole.sol +23 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/access-control/AccessControlModified.sol +14 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/access-control/AccessManagedERC20MintBase.sol +16 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/access-control/MyContractOwnable.sol +17 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/account/MyAccountEIP7702.sol +20 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/account/MyFactoryAccount.sol +37 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/governance/MyGovernor.sol +80 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/governance/MyToken.sol +21 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/governance/MyTokenTimestampBased.sol +32 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/governance/MyTokenWrapped.sol +28 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/token/ERC1155/GameItems.sol +21 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/token/ERC1155/MyERC115HolderContract.sol +7 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/token/ERC20/GLDToken.sol +11 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/token/ERC6909/ERC6909GameItems.sol +26 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/token/ERC721/GameItem.sol +19 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/utilities/Base64NFT.sol +27 -0
- package/lib/openzeppelin-contracts/contracts/mocks/docs/utilities/Multicall.sol +15 -0
- package/lib/openzeppelin-contracts/contracts/mocks/governance/GovernorCountingOverridableMock.sol +18 -0
- package/lib/openzeppelin-contracts/contracts/mocks/governance/GovernorFractionalMock.sol +14 -0
- package/lib/openzeppelin-contracts/contracts/mocks/governance/GovernorMock.sol +14 -0
- package/lib/openzeppelin-contracts/contracts/mocks/governance/GovernorNoncesKeyedMock.sol +44 -0
- package/lib/openzeppelin-contracts/contracts/mocks/governance/GovernorPreventLateQuorumMock.sol +40 -0
- package/lib/openzeppelin-contracts/contracts/mocks/governance/GovernorProposalGuardianMock.sol +27 -0
- package/lib/openzeppelin-contracts/contracts/mocks/governance/GovernorSequentialProposalIdMock.sol +39 -0
- package/lib/openzeppelin-contracts/contracts/mocks/governance/GovernorStorageMock.sol +79 -0
- package/lib/openzeppelin-contracts/contracts/mocks/governance/GovernorSuperQuorumMock.sol +95 -0
- package/lib/openzeppelin-contracts/contracts/mocks/governance/GovernorTimelockAccessMock.sol +70 -0
- package/lib/openzeppelin-contracts/contracts/mocks/governance/GovernorTimelockCompoundMock.sol +69 -0
- package/lib/openzeppelin-contracts/contracts/mocks/governance/GovernorTimelockControlMock.sol +69 -0
- package/lib/openzeppelin-contracts/contracts/mocks/governance/GovernorVoteMock.sol +20 -0
- package/lib/openzeppelin-contracts/contracts/mocks/governance/GovernorVotesSuperQuorumFractionMock.sol +37 -0
- package/lib/openzeppelin-contracts/contracts/mocks/governance/GovernorWithParamsMock.sol +51 -0
- package/lib/openzeppelin-contracts/contracts/mocks/proxy/BadBeacon.sol +11 -0
- package/lib/openzeppelin-contracts/contracts/mocks/proxy/ClashingImplementation.sol +19 -0
- package/lib/openzeppelin-contracts/contracts/mocks/proxy/ERC1967ProxyUnsafe.sol +13 -0
- package/lib/openzeppelin-contracts/contracts/mocks/proxy/UUPSUpgradeableMock.sol +35 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC1155ReceiverMock.sol +74 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC1363ForceApproveMock.sol +13 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC1363NoReturnMock.sol +33 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC1363ReceiverMock.sol +52 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC1363ReturnFalseMock.sol +34 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC1363SpenderMock.sol +47 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC20ApprovalMock.sol +10 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC20BridgeableMock.sol +30 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC20DecimalsMock.sol +17 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC20ExcessDecimalsMock.sol +9 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC20FlashMintMock.sol +26 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC20ForceApproveMock.sol +13 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC20GetterHelper.sol +38 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC20Mock.sol +16 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC20MulticallMock.sol +8 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC20NoReturnMock.sol +30 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC20Reentrant.sol +39 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC20ReturnFalseMock.sol +19 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC20VotesAdditionalCheckpointsMock.sol +31 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC20VotesLegacyMock.sol +253 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC20VotesTimestampMock.sol +29 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC4626LimitsMock.sol +23 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC4626Mock.sol +17 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC4626OffsetMock.sol +17 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC4646FeesMock.sol +40 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC721ConsecutiveEnumerableMock.sol +42 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC721ConsecutiveMock.sol +61 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC721ReceiverMock.sol +47 -0
- package/lib/openzeppelin-contracts/contracts/mocks/token/ERC721URIStorageMock.sol +17 -0
- package/lib/openzeppelin-contracts/contracts/mocks/utils/cryptography/ERC7739Mock.sol +12 -0
- package/lib/openzeppelin-contracts/contracts/package.json +32 -0
- package/lib/openzeppelin-contracts/contracts/proxy/Clones.sol +294 -0
- package/lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Proxy.sol +62 -0
- package/lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Utils.sol +177 -0
- package/lib/openzeppelin-contracts/contracts/proxy/Proxy.sol +69 -0
- package/lib/openzeppelin-contracts/contracts/proxy/README.adoc +87 -0
- package/lib/openzeppelin-contracts/contracts/proxy/beacon/BeaconProxy.sol +57 -0
- package/lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol +16 -0
- package/lib/openzeppelin-contracts/contracts/proxy/beacon/UpgradeableBeacon.sol +70 -0
- package/lib/openzeppelin-contracts/contracts/proxy/transparent/ProxyAdmin.sol +45 -0
- package/lib/openzeppelin-contracts/contracts/proxy/transparent/TransparentUpgradeableProxy.sol +118 -0
- package/lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol +238 -0
- package/lib/openzeppelin-contracts/contracts/proxy/utils/UUPSUpgradeable.sol +148 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC1155/ERC1155.sol +416 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol +123 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol +59 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC1155/README.adoc +43 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC1155/extensions/ERC1155Burnable.sol +28 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC1155/extensions/ERC1155Pausable.sol +38 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC1155/extensions/ERC1155Supply.sol +88 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC1155/extensions/ERC1155URIStorage.sol +58 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol +20 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC1155/utils/ERC1155Holder.sol +42 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC1155/utils/ERC1155Utils.sol +88 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol +305 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol +79 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/README.adoc +81 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC1363.sol +135 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Burnable.sol +39 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Capped.sol +54 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Crosschain.sol +38 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20FlashMint.sol +130 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Pausable.sol +33 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Permit.sol +77 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol +83 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Wrapper.sol +89 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol +315 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol +26 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol +90 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-ERC20Bridgeable.sol +51 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-ERC20TemporaryApproval.sol +119 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/utils/ERC1363Utils.sol +95 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol +280 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC6909/ERC6909.sol +224 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC6909/README.adoc +27 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC6909/extensions/ERC6909ContentURI.sol +59 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC6909/extensions/ERC6909Metadata.sol +83 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC6909/extensions/ERC6909TokenSupply.sol +41 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC721/ERC721.sol +433 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol +135 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol +28 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC721/README.adoc +69 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC721/extensions/ERC721Burnable.sol +26 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC721/extensions/ERC721Consecutive.sol +176 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC721/extensions/ERC721Enumerable.sol +165 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC721/extensions/ERC721Pausable.sol +37 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC721/extensions/ERC721Royalty.sol +26 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC721/extensions/ERC721URIStorage.sol +62 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC721/extensions/ERC721Votes.sol +47 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC721/extensions/ERC721Wrapper.sol +102 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Enumerable.sol +29 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol +27 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC721/utils/ERC721Holder.sol +26 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC721/utils/ERC721Utils.sol +50 -0
- package/lib/openzeppelin-contracts/contracts/token/common/ERC2981.sol +139 -0
- package/lib/openzeppelin-contracts/contracts/token/common/README.adoc +10 -0
- package/lib/openzeppelin-contracts/contracts/utils/Address.sol +167 -0
- package/lib/openzeppelin-contracts/contracts/utils/Arrays.sol +888 -0
- package/lib/openzeppelin-contracts/contracts/utils/Base58.sol +240 -0
- package/lib/openzeppelin-contracts/contracts/utils/Base64.sol +234 -0
- package/lib/openzeppelin-contracts/contracts/utils/Blockhash.sol +54 -0
- package/lib/openzeppelin-contracts/contracts/utils/Bytes.sol +332 -0
- package/lib/openzeppelin-contracts/contracts/utils/CAIP10.sol +54 -0
- package/lib/openzeppelin-contracts/contracts/utils/CAIP2.sol +51 -0
- package/lib/openzeppelin-contracts/contracts/utils/Calldata.sol +25 -0
- package/lib/openzeppelin-contracts/contracts/utils/Comparators.sol +19 -0
- package/lib/openzeppelin-contracts/contracts/utils/Context.sol +28 -0
- package/lib/openzeppelin-contracts/contracts/utils/Create2.sol +91 -0
- package/lib/openzeppelin-contracts/contracts/utils/Errors.sol +34 -0
- package/lib/openzeppelin-contracts/contracts/utils/LowLevelCall.sol +127 -0
- package/lib/openzeppelin-contracts/contracts/utils/Memory.sol +146 -0
- package/lib/openzeppelin-contracts/contracts/utils/Multicall.sol +37 -0
- package/lib/openzeppelin-contracts/contracts/utils/Nonces.sol +46 -0
- package/lib/openzeppelin-contracts/contracts/utils/NoncesKeyed.sol +74 -0
- package/lib/openzeppelin-contracts/contracts/utils/Packing.sol +1656 -0
- package/lib/openzeppelin-contracts/contracts/utils/Panic.sol +57 -0
- package/lib/openzeppelin-contracts/contracts/utils/Pausable.sol +112 -0
- package/lib/openzeppelin-contracts/contracts/utils/README.adoc +160 -0
- package/lib/openzeppelin-contracts/contracts/utils/RLP.sol +476 -0
- package/lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol +119 -0
- package/lib/openzeppelin-contracts/contracts/utils/ReentrancyGuardTransient.sol +84 -0
- package/lib/openzeppelin-contracts/contracts/utils/RelayedCall.sol +133 -0
- package/lib/openzeppelin-contracts/contracts/utils/ShortStrings.sol +122 -0
- package/lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol +155 -0
- package/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol +143 -0
- package/lib/openzeppelin-contracts/contracts/utils/Strings.sol +508 -0
- package/lib/openzeppelin-contracts/contracts/utils/TransientSlot.sol +183 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol +284 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol +160 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/Hashes.sol +31 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol +510 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol +228 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol +408 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/README.adoc +76 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/RSA.sol +154 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/SignatureChecker.sol +191 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/TrieProof.sol +230 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/WebAuthn.sol +261 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/draft-ERC7739Utils.sol +207 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/signers/AbstractSigner.sol +23 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/signers/MultiSignerERC7913.sol +259 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/signers/MultiSignerERC7913Weighted.sol +208 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/signers/SignerECDSA.sol +56 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/signers/SignerEIP7702.sol +25 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/signers/SignerERC7913.sol +63 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/signers/SignerP256.sol +64 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/signers/SignerRSA.sol +65 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/signers/SignerWebAuthn.sol +51 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/signers/draft-ERC7739.sol +98 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/verifiers/ERC7913P256Verifier.sol +29 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/verifiers/ERC7913RSAVerifier.sol +23 -0
- package/lib/openzeppelin-contracts/contracts/utils/cryptography/verifiers/ERC7913WebAuthnVerifier.sol +35 -0
- package/lib/openzeppelin-contracts/contracts/utils/draft-InteroperableAddress.sol +235 -0
- package/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol +25 -0
- package/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol +142 -0
- package/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol +25 -0
- package/lib/openzeppelin-contracts/contracts/utils/math/Math.sol +763 -0
- package/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol +1162 -0
- package/lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol +68 -0
- package/lib/openzeppelin-contracts/contracts/utils/structs/Accumulators.sol +130 -0
- package/lib/openzeppelin-contracts/contracts/utils/structs/BitMaps.sol +60 -0
- package/lib/openzeppelin-contracts/contracts/utils/structs/Checkpoints.sol +833 -0
- package/lib/openzeppelin-contracts/contracts/utils/structs/CircularBuffer.sol +152 -0
- package/lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol +237 -0
- package/lib/openzeppelin-contracts/contracts/utils/structs/EnumerableMap.sol +1443 -0
- package/lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol +895 -0
- package/lib/openzeppelin-contracts/contracts/utils/structs/Heap.sol +259 -0
- package/lib/openzeppelin-contracts/contracts/utils/structs/MerkleTree.sol +267 -0
- package/lib/openzeppelin-contracts/contracts/utils/types/Time.sol +133 -0
- package/lib/openzeppelin-contracts/contracts/vendor/compound/ICompoundTimelock.sol +86 -0
- package/lib/openzeppelin-contracts/contracts/vendor/compound/LICENSE +11 -0
- package/lib/openzeppelin-contracts/docs/README.md +16 -0
- package/lib/openzeppelin-contracts/docs/antora.yml +7 -0
- package/lib/openzeppelin-contracts/docs/config.js +21 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/access-control-multiple.svg +97 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/access-manager-functions.svg +47 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/access-manager.svg +99 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-attack-3a.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-attack-3b.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-attack-6.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-attack.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-deposit.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-mint.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-rate-linear.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-rate-loglog.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-rate-loglogext.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/tally-exec.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/tally-vote.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/nav.adoc +29 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/access-control.adoc +339 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/account-abstraction.adoc +100 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/accounts.adoc +354 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/backwards-compatibility.adoc +50 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/eoa-delegation.adoc +143 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc1155.adoc +118 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc20-supply.adoc +71 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc20.adoc +67 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc4626.adoc +214 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc6909.adoc +47 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc721.adoc +58 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/extending-contracts.adoc +51 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/faq.adoc +13 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/governance.adoc +242 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/index.adoc +100 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/multisig.adoc +308 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/tokens.adoc +31 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/upgradeable.adoc +77 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/utilities.adoc +634 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/wizard.adoc +15 -0
- package/lib/openzeppelin-contracts/docs/templates/contract.hbs +141 -0
- package/lib/openzeppelin-contracts/docs/templates/helpers.js +46 -0
- package/lib/openzeppelin-contracts/docs/templates/page.hbs +4 -0
- package/lib/openzeppelin-contracts/docs/templates/properties.js +88 -0
- package/lib/openzeppelin-contracts/eslint.config.mjs +29 -0
- package/lib/openzeppelin-contracts/foundry.toml +20 -0
- package/lib/openzeppelin-contracts/fv/Makefile +54 -0
- package/lib/openzeppelin-contracts/fv/README.md +60 -0
- package/lib/openzeppelin-contracts/fv/diff/access_manager_AccessManager.sol.patch +97 -0
- package/lib/openzeppelin-contracts/fv/diff/account_extensions_draft-AccountERC7579.sol.patch +25 -0
- package/lib/openzeppelin-contracts/fv/diff/token_ERC721_ERC721.sol.patch +11 -0
- package/lib/openzeppelin-contracts/fv/harnesses/AccessControlDefaultAdminRulesHarness.sol +46 -0
- package/lib/openzeppelin-contracts/fv/harnesses/AccessControlHarness.sol +6 -0
- package/lib/openzeppelin-contracts/fv/harnesses/AccessManagedHarness.sol +36 -0
- package/lib/openzeppelin-contracts/fv/harnesses/AccessManagerHarness.sol +116 -0
- package/lib/openzeppelin-contracts/fv/harnesses/AccountHarness.sol +60 -0
- package/lib/openzeppelin-contracts/fv/harnesses/DoubleEndedQueueHarness.sol +58 -0
- package/lib/openzeppelin-contracts/fv/harnesses/ERC20FlashMintHarness.sol +36 -0
- package/lib/openzeppelin-contracts/fv/harnesses/ERC20PermitHarness.sol +16 -0
- package/lib/openzeppelin-contracts/fv/harnesses/ERC20WrapperHarness.sol +22 -0
- package/lib/openzeppelin-contracts/fv/harnesses/ERC3156FlashBorrowerHarness.sol +13 -0
- package/lib/openzeppelin-contracts/fv/harnesses/ERC721Harness.sol +37 -0
- package/lib/openzeppelin-contracts/fv/harnesses/ERC721ReceiverHarness.sol +11 -0
- package/lib/openzeppelin-contracts/fv/harnesses/EnumerableMapHarness.sol +55 -0
- package/lib/openzeppelin-contracts/fv/harnesses/EnumerableSetHarness.sol +35 -0
- package/lib/openzeppelin-contracts/fv/harnesses/InitializableHarness.sol +23 -0
- package/lib/openzeppelin-contracts/fv/harnesses/NoncesHarness.sol +14 -0
- package/lib/openzeppelin-contracts/fv/harnesses/Ownable2StepHarness.sol +10 -0
- package/lib/openzeppelin-contracts/fv/harnesses/OwnableHarness.sol +10 -0
- package/lib/openzeppelin-contracts/fv/harnesses/PausableHarness.sol +18 -0
- package/lib/openzeppelin-contracts/fv/harnesses/TimelockControllerHarness.sol +13 -0
- package/lib/openzeppelin-contracts/fv/reports/2021-10.pdf +0 -0
- package/lib/openzeppelin-contracts/fv/reports/2022-03.pdf +0 -0
- package/lib/openzeppelin-contracts/fv/reports/2022-05.pdf +0 -0
- package/lib/openzeppelin-contracts/fv/run.js +68 -0
- package/lib/openzeppelin-contracts/fv/specs/AccessControl.conf +8 -0
- package/lib/openzeppelin-contracts/fv/specs/AccessControl.spec +119 -0
- package/lib/openzeppelin-contracts/fv/specs/AccessControlDefaultAdminRules.conf +8 -0
- package/lib/openzeppelin-contracts/fv/specs/AccessControlDefaultAdminRules.spec +467 -0
- package/lib/openzeppelin-contracts/fv/specs/AccessManaged.conf +14 -0
- package/lib/openzeppelin-contracts/fv/specs/AccessManaged.spec +49 -0
- package/lib/openzeppelin-contracts/fv/specs/AccessManager.conf +10 -0
- package/lib/openzeppelin-contracts/fv/specs/AccessManager.spec +837 -0
- package/lib/openzeppelin-contracts/fv/specs/Account.conf +9 -0
- package/lib/openzeppelin-contracts/fv/specs/Account.spec +490 -0
- package/lib/openzeppelin-contracts/fv/specs/DoubleEndedQueue.conf +8 -0
- package/lib/openzeppelin-contracts/fv/specs/DoubleEndedQueue.spec +300 -0
- package/lib/openzeppelin-contracts/fv/specs/ERC20.conf +9 -0
- package/lib/openzeppelin-contracts/fv/specs/ERC20.spec +352 -0
- package/lib/openzeppelin-contracts/fv/specs/ERC20FlashMint.conf +10 -0
- package/lib/openzeppelin-contracts/fv/specs/ERC20FlashMint.spec +55 -0
- package/lib/openzeppelin-contracts/fv/specs/ERC20Wrapper.conf +13 -0
- package/lib/openzeppelin-contracts/fv/specs/ERC20Wrapper.spec +226 -0
- package/lib/openzeppelin-contracts/fv/specs/ERC721.conf +10 -0
- package/lib/openzeppelin-contracts/fv/specs/ERC721.spec +695 -0
- package/lib/openzeppelin-contracts/fv/specs/EnumerableMap.conf +8 -0
- package/lib/openzeppelin-contracts/fv/specs/EnumerableMap.spec +364 -0
- package/lib/openzeppelin-contracts/fv/specs/EnumerableSet.conf +8 -0
- package/lib/openzeppelin-contracts/fv/specs/EnumerableSet.spec +272 -0
- package/lib/openzeppelin-contracts/fv/specs/Initializable.conf +8 -0
- package/lib/openzeppelin-contracts/fv/specs/Initializable.spec +176 -0
- package/lib/openzeppelin-contracts/fv/specs/Nonces.conf +8 -0
- package/lib/openzeppelin-contracts/fv/specs/Nonces.spec +92 -0
- package/lib/openzeppelin-contracts/fv/specs/Ownable.conf +8 -0
- package/lib/openzeppelin-contracts/fv/specs/Ownable.spec +77 -0
- package/lib/openzeppelin-contracts/fv/specs/Ownable2Step.conf +8 -0
- package/lib/openzeppelin-contracts/fv/specs/Ownable2Step.spec +108 -0
- package/lib/openzeppelin-contracts/fv/specs/Pausable.conf +8 -0
- package/lib/openzeppelin-contracts/fv/specs/Pausable.spec +96 -0
- package/lib/openzeppelin-contracts/fv/specs/TimelockController.conf +10 -0
- package/lib/openzeppelin-contracts/fv/specs/TimelockController.spec +299 -0
- package/lib/openzeppelin-contracts/fv/specs/helpers/helpers.spec +13 -0
- package/lib/openzeppelin-contracts/fv/specs/methods/IAccessControl.spec +8 -0
- package/lib/openzeppelin-contracts/fv/specs/methods/IAccessControlDefaultAdminRules.spec +36 -0
- package/lib/openzeppelin-contracts/fv/specs/methods/IAccessManaged.spec +5 -0
- package/lib/openzeppelin-contracts/fv/specs/methods/IAccessManager.spec +33 -0
- package/lib/openzeppelin-contracts/fv/specs/methods/IAccount.spec +34 -0
- package/lib/openzeppelin-contracts/fv/specs/methods/IERC20.spec +11 -0
- package/lib/openzeppelin-contracts/fv/specs/methods/IERC2612.spec +5 -0
- package/lib/openzeppelin-contracts/fv/specs/methods/IERC3156FlashBorrower.spec +3 -0
- package/lib/openzeppelin-contracts/fv/specs/methods/IERC3156FlashLender.spec +5 -0
- package/lib/openzeppelin-contracts/fv/specs/methods/IERC5313.spec +3 -0
- package/lib/openzeppelin-contracts/fv/specs/methods/IERC721.spec +17 -0
- package/lib/openzeppelin-contracts/fv/specs/methods/IERC721Receiver.spec +3 -0
- package/lib/openzeppelin-contracts/fv/specs/methods/IOwnable.spec +5 -0
- package/lib/openzeppelin-contracts/fv/specs/methods/IOwnable2Step.spec +7 -0
- package/lib/openzeppelin-contracts/fv-requirements.txt +4 -0
- package/lib/openzeppelin-contracts/hardhat/async-test-sanity.js +10 -0
- package/lib/openzeppelin-contracts/hardhat/env-artifacts.js +29 -0
- package/lib/openzeppelin-contracts/hardhat/ignore-unreachable-warnings.js +45 -0
- package/lib/openzeppelin-contracts/hardhat/remappings.js +18 -0
- package/lib/openzeppelin-contracts/hardhat/skip-foundry-tests.js +6 -0
- package/lib/openzeppelin-contracts/hardhat/task-test-get-files.js +25 -0
- package/lib/openzeppelin-contracts/hardhat.config.js +124 -0
- package/lib/openzeppelin-contracts/logo.svg +15 -0
- package/lib/openzeppelin-contracts/netlify.toml +3 -0
- package/lib/openzeppelin-contracts/package-lock.json +11140 -0
- package/lib/openzeppelin-contracts/package.json +108 -0
- package/lib/openzeppelin-contracts/remappings.txt +1 -0
- package/lib/openzeppelin-contracts/renovate.json +4 -0
- package/lib/openzeppelin-contracts/scripts/checks/compare-layout.js +28 -0
- package/lib/openzeppelin-contracts/scripts/checks/compareGasReports.js +249 -0
- package/lib/openzeppelin-contracts/scripts/checks/coverage.sh +24 -0
- package/lib/openzeppelin-contracts/scripts/checks/extract-layout.js +39 -0
- package/lib/openzeppelin-contracts/scripts/checks/generation.sh +6 -0
- package/lib/openzeppelin-contracts/scripts/checks/inheritance-ordering.js +55 -0
- package/lib/openzeppelin-contracts/scripts/checks/pragma-validity.js +45 -0
- package/lib/openzeppelin-contracts/scripts/fetch-common-contracts.js +50 -0
- package/lib/openzeppelin-contracts/scripts/gen-nav.js +81 -0
- package/lib/openzeppelin-contracts/scripts/generate/format-lines.js +16 -0
- package/lib/openzeppelin-contracts/scripts/generate/helpers/sanitize.js +5 -0
- package/lib/openzeppelin-contracts/scripts/generate/run.js +61 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/Arrays.js +505 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/Arrays.opts.js +9 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/Checkpoints.js +242 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/Checkpoints.opts.js +18 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/Checkpoints.t.js +141 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/Enumerable.opts.js +56 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/EnumerableMap.js +464 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/EnumerableSet.js +470 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/MerkleProof.js +186 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/MerkleProof.opts.js +11 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/Packing.js +92 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/Packing.opts.js +3 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/Packing.t.js +48 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/SafeCast.js +136 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/Slot.opts.js +15 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/SlotDerivation.js +119 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/SlotDerivation.t.js +127 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/StorageSlot.js +77 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/StorageSlotMock.js +57 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/TransientSlot.js +80 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/TransientSlotMock.js +35 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/conversion.js +34 -0
- package/lib/openzeppelin-contracts/scripts/get-contracts-metadata.js +55 -0
- package/lib/openzeppelin-contracts/scripts/git-user-config.sh +6 -0
- package/lib/openzeppelin-contracts/scripts/helpers.js +7 -0
- package/lib/openzeppelin-contracts/scripts/minimize-pragma.js +140 -0
- package/lib/openzeppelin-contracts/scripts/prepack.sh +23 -0
- package/lib/openzeppelin-contracts/scripts/prepare-docs.sh +26 -0
- package/lib/openzeppelin-contracts/scripts/release/format-changelog.js +33 -0
- package/lib/openzeppelin-contracts/scripts/release/synchronize-versions.js +15 -0
- package/lib/openzeppelin-contracts/scripts/release/update-comment.js +34 -0
- package/lib/openzeppelin-contracts/scripts/release/version.sh +11 -0
- package/lib/openzeppelin-contracts/scripts/release/workflow/check-upgradeable.sh +27 -0
- package/lib/openzeppelin-contracts/scripts/release/workflow/exit-prerelease.sh +8 -0
- package/lib/openzeppelin-contracts/scripts/release/workflow/github-release.js +48 -0
- package/lib/openzeppelin-contracts/scripts/release/workflow/integrity-check.sh +20 -0
- package/lib/openzeppelin-contracts/scripts/release/workflow/pack.sh +26 -0
- package/lib/openzeppelin-contracts/scripts/release/workflow/publish.sh +26 -0
- package/lib/openzeppelin-contracts/scripts/release/workflow/rerun.js +7 -0
- package/lib/openzeppelin-contracts/scripts/release/workflow/set-changesets-pr-title.js +17 -0
- package/lib/openzeppelin-contracts/scripts/release/workflow/start.sh +35 -0
- package/lib/openzeppelin-contracts/scripts/release/workflow/state.js +112 -0
- package/lib/openzeppelin-contracts/scripts/remove-ignored-artifacts.js +45 -0
- package/lib/openzeppelin-contracts/scripts/set-max-old-space-size.sh +10 -0
- package/lib/openzeppelin-contracts/scripts/solc-versions.js +15 -0
- package/lib/openzeppelin-contracts/scripts/solhint-custom/index.js +118 -0
- package/lib/openzeppelin-contracts/scripts/solhint-custom/package.json +8 -0
- package/lib/openzeppelin-contracts/scripts/update-docs-branch.js +65 -0
- package/lib/openzeppelin-contracts/scripts/upgradeable/README.md +21 -0
- package/lib/openzeppelin-contracts/scripts/upgradeable/alias/Initializable.sol +5 -0
- package/lib/openzeppelin-contracts/scripts/upgradeable/alias/UUPSUpgradeable.sol +5 -0
- package/lib/openzeppelin-contracts/scripts/upgradeable/patch-apply.sh +19 -0
- package/lib/openzeppelin-contracts/scripts/upgradeable/patch-save.sh +18 -0
- package/lib/openzeppelin-contracts/scripts/upgradeable/transpile-onto.sh +54 -0
- package/lib/openzeppelin-contracts/scripts/upgradeable/transpile.sh +50 -0
- package/lib/openzeppelin-contracts/scripts/upgradeable/upgradeable.patch +390 -0
- package/lib/openzeppelin-contracts/slither.config.json +4 -0
- package/lib/openzeppelin-contracts/solhint.config.js +29 -0
- package/lib/openzeppelin-contracts/test/TESTING.md +3 -0
- package/lib/openzeppelin-contracts/test/access/AccessControl.behavior.js +874 -0
- package/lib/openzeppelin-contracts/test/access/AccessControl.test.js +19 -0
- package/lib/openzeppelin-contracts/test/access/Ownable.test.js +79 -0
- package/lib/openzeppelin-contracts/test/access/Ownable2Step.test.js +102 -0
- package/lib/openzeppelin-contracts/test/access/extensions/AccessControlDefaultAdminRules.test.js +32 -0
- package/lib/openzeppelin-contracts/test/access/extensions/AccessControlEnumerable.test.js +24 -0
- package/lib/openzeppelin-contracts/test/access/manager/AccessManaged.test.js +146 -0
- package/lib/openzeppelin-contracts/test/access/manager/AccessManager.behavior.js +257 -0
- package/lib/openzeppelin-contracts/test/access/manager/AccessManager.predicate.js +456 -0
- package/lib/openzeppelin-contracts/test/access/manager/AccessManager.test.js +2489 -0
- package/lib/openzeppelin-contracts/test/access/manager/AuthorityUtils.test.js +112 -0
- package/lib/openzeppelin-contracts/test/account/Account.behavior.js +144 -0
- package/lib/openzeppelin-contracts/test/account/Account.test.js +48 -0
- package/lib/openzeppelin-contracts/test/account/AccountECDSA.test.js +52 -0
- package/lib/openzeppelin-contracts/test/account/AccountEIP7702.t.sol +116 -0
- package/lib/openzeppelin-contracts/test/account/AccountEIP7702.test.js +52 -0
- package/lib/openzeppelin-contracts/test/account/AccountERC7913.test.js +138 -0
- package/lib/openzeppelin-contracts/test/account/AccountMultiSigner.test.js +326 -0
- package/lib/openzeppelin-contracts/test/account/AccountMultiSignerWeighted.test.js +312 -0
- package/lib/openzeppelin-contracts/test/account/AccountP256.test.js +58 -0
- package/lib/openzeppelin-contracts/test/account/AccountRSA.test.js +58 -0
- package/lib/openzeppelin-contracts/test/account/AccountWebAuthn.test.js +88 -0
- package/lib/openzeppelin-contracts/test/account/examples/AccountEIP7702WithModulesMock.test.js +99 -0
- package/lib/openzeppelin-contracts/test/account/extensions/AccountERC7579.behavior.js +621 -0
- package/lib/openzeppelin-contracts/test/account/extensions/AccountERC7579.test.js +60 -0
- package/lib/openzeppelin-contracts/test/account/extensions/AccountERC7579Hooked.test.js +60 -0
- package/lib/openzeppelin-contracts/test/account/extensions/ERC7821.behavior.js +145 -0
- package/lib/openzeppelin-contracts/test/account/utils/EIP7702Utils.test.js +53 -0
- package/lib/openzeppelin-contracts/test/account/utils/draft-ERC4337Utils.test.js +594 -0
- package/lib/openzeppelin-contracts/test/account/utils/draft-ERC7579Utils.t.sol +434 -0
- package/lib/openzeppelin-contracts/test/account/utils/draft-ERC7579Utils.test.js +399 -0
- package/lib/openzeppelin-contracts/test/crosschain/BridgeERC20.behavior.js +163 -0
- package/lib/openzeppelin-contracts/test/crosschain/BridgeERC20.test.js +46 -0
- package/lib/openzeppelin-contracts/test/crosschain/ERC7786Recipient.test.js +73 -0
- package/lib/openzeppelin-contracts/test/finance/VestingWallet.behavior.js +87 -0
- package/lib/openzeppelin-contracts/test/finance/VestingWallet.test.js +65 -0
- package/lib/openzeppelin-contracts/test/finance/VestingWalletCliff.test.js +70 -0
- package/lib/openzeppelin-contracts/test/governance/Governor.t.sol +59 -0
- package/lib/openzeppelin-contracts/test/governance/Governor.test.js +980 -0
- package/lib/openzeppelin-contracts/test/governance/TimelockController.test.js +1279 -0
- package/lib/openzeppelin-contracts/test/governance/extensions/GovernorCountingFractional.test.js +248 -0
- package/lib/openzeppelin-contracts/test/governance/extensions/GovernorCountingOverridable.test.js +346 -0
- package/lib/openzeppelin-contracts/test/governance/extensions/GovernorERC721.test.js +131 -0
- package/lib/openzeppelin-contracts/test/governance/extensions/GovernorNoncesKeyed.test.js +243 -0
- package/lib/openzeppelin-contracts/test/governance/extensions/GovernorPreventLateQuorum.test.js +185 -0
- package/lib/openzeppelin-contracts/test/governance/extensions/GovernorProposalGuardian.test.js +132 -0
- package/lib/openzeppelin-contracts/test/governance/extensions/GovernorSequentialProposalId.test.js +202 -0
- package/lib/openzeppelin-contracts/test/governance/extensions/GovernorStorage.test.js +175 -0
- package/lib/openzeppelin-contracts/test/governance/extensions/GovernorSuperQuorum.test.js +168 -0
- package/lib/openzeppelin-contracts/test/governance/extensions/GovernorSuperQuorumGreaterThanQuorum.t.sol +83 -0
- package/lib/openzeppelin-contracts/test/governance/extensions/GovernorTimelockAccess.test.js +864 -0
- package/lib/openzeppelin-contracts/test/governance/extensions/GovernorTimelockCompound.test.js +448 -0
- package/lib/openzeppelin-contracts/test/governance/extensions/GovernorTimelockControl.test.js +504 -0
- package/lib/openzeppelin-contracts/test/governance/extensions/GovernorVotesQuorumFraction.test.js +165 -0
- package/lib/openzeppelin-contracts/test/governance/extensions/GovernorVotesSuperQuorumFraction.test.js +160 -0
- package/lib/openzeppelin-contracts/test/governance/extensions/GovernorWithParams.test.js +245 -0
- package/lib/openzeppelin-contracts/test/governance/utils/ERC6372.behavior.js +28 -0
- package/lib/openzeppelin-contracts/test/governance/utils/Votes.behavior.js +325 -0
- package/lib/openzeppelin-contracts/test/governance/utils/Votes.test.js +102 -0
- package/lib/openzeppelin-contracts/test/governance/utils/VotesExtended.test.js +152 -0
- package/lib/openzeppelin-contracts/test/helpers/access-manager.js +85 -0
- package/lib/openzeppelin-contracts/test/helpers/account.js +16 -0
- package/lib/openzeppelin-contracts/test/helpers/chains.js +56 -0
- package/lib/openzeppelin-contracts/test/helpers/constants.js +7 -0
- package/lib/openzeppelin-contracts/test/helpers/deploy.js +14 -0
- package/lib/openzeppelin-contracts/test/helpers/eip712-types.js +61 -0
- package/lib/openzeppelin-contracts/test/helpers/eip712.js +45 -0
- package/lib/openzeppelin-contracts/test/helpers/enums.js +15 -0
- package/lib/openzeppelin-contracts/test/helpers/erc4337.js +244 -0
- package/lib/openzeppelin-contracts/test/helpers/erc7579.js +58 -0
- package/lib/openzeppelin-contracts/test/helpers/erc7739.js +118 -0
- package/lib/openzeppelin-contracts/test/helpers/governance.js +218 -0
- package/lib/openzeppelin-contracts/test/helpers/iterate.js +41 -0
- package/lib/openzeppelin-contracts/test/helpers/math.js +33 -0
- package/lib/openzeppelin-contracts/test/helpers/methods.js +14 -0
- package/lib/openzeppelin-contracts/test/helpers/precompiles.js +12 -0
- package/lib/openzeppelin-contracts/test/helpers/random.js +26 -0
- package/lib/openzeppelin-contracts/test/helpers/signers.js +222 -0
- package/lib/openzeppelin-contracts/test/helpers/storage.js +48 -0
- package/lib/openzeppelin-contracts/test/helpers/strings.js +5 -0
- package/lib/openzeppelin-contracts/test/helpers/time.js +33 -0
- package/lib/openzeppelin-contracts/test/helpers/trie.js +79 -0
- package/lib/openzeppelin-contracts/test/helpers/txpool.js +28 -0
- package/lib/openzeppelin-contracts/test/metatx/ERC2771Context.test.js +109 -0
- package/lib/openzeppelin-contracts/test/metatx/ERC2771Forwarder.t.sol +279 -0
- package/lib/openzeppelin-contracts/test/metatx/ERC2771Forwarder.test.js +384 -0
- package/lib/openzeppelin-contracts/test/proxy/Clones.behaviour.js +160 -0
- package/lib/openzeppelin-contracts/test/proxy/Clones.t.sol +91 -0
- package/lib/openzeppelin-contracts/test/proxy/Clones.test.js +177 -0
- package/lib/openzeppelin-contracts/test/proxy/ERC1967/ERC1967Proxy.test.js +36 -0
- package/lib/openzeppelin-contracts/test/proxy/ERC1967/ERC1967Utils.test.js +162 -0
- package/lib/openzeppelin-contracts/test/proxy/Proxy.behaviour.js +198 -0
- package/lib/openzeppelin-contracts/test/proxy/beacon/BeaconProxy.test.js +141 -0
- package/lib/openzeppelin-contracts/test/proxy/beacon/UpgradeableBeacon.test.js +55 -0
- package/lib/openzeppelin-contracts/test/proxy/transparent/ProxyAdmin.test.js +82 -0
- package/lib/openzeppelin-contracts/test/proxy/transparent/TransparentUpgradeableProxy.behaviour.js +367 -0
- package/lib/openzeppelin-contracts/test/proxy/transparent/TransparentUpgradeableProxy.test.js +28 -0
- package/lib/openzeppelin-contracts/test/proxy/utils/Initializable.test.js +216 -0
- package/lib/openzeppelin-contracts/test/proxy/utils/UUPSUpgradeable.test.js +120 -0
- package/lib/openzeppelin-contracts/test/sanity.test.js +27 -0
- package/lib/openzeppelin-contracts/test/token/ERC1155/ERC1155.behavior.js +865 -0
- package/lib/openzeppelin-contracts/test/token/ERC1155/ERC1155.test.js +258 -0
- package/lib/openzeppelin-contracts/test/token/ERC1155/extensions/ERC1155Burnable.test.js +66 -0
- package/lib/openzeppelin-contracts/test/token/ERC1155/extensions/ERC1155Pausable.test.js +105 -0
- package/lib/openzeppelin-contracts/test/token/ERC1155/extensions/ERC1155Supply.test.js +119 -0
- package/lib/openzeppelin-contracts/test/token/ERC1155/extensions/ERC1155URIStorage.test.js +70 -0
- package/lib/openzeppelin-contracts/test/token/ERC1155/utils/ERC1155Holder.test.js +56 -0
- package/lib/openzeppelin-contracts/test/token/ERC1155/utils/ERC1155Utils.test.js +299 -0
- package/lib/openzeppelin-contracts/test/token/ERC20/ERC20.behavior.js +269 -0
- package/lib/openzeppelin-contracts/test/token/ERC20/ERC20.test.js +199 -0
- package/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC1363.test.js +370 -0
- package/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Burnable.test.js +105 -0
- package/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Capped.test.js +55 -0
- package/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Crosschain.test.js +83 -0
- package/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20FlashMint.test.js +164 -0
- package/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Pausable.test.js +129 -0
- package/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Permit.test.js +109 -0
- package/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Votes.test.js +546 -0
- package/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Wrapper.test.js +203 -0
- package/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC4626.t.sol +41 -0
- package/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC4626.test.js +888 -0
- package/lib/openzeppelin-contracts/test/token/ERC20/extensions/draft-ERC20Bridgeable.test.js +89 -0
- package/lib/openzeppelin-contracts/test/token/ERC20/extensions/draft-ERC20TemporaryApproval.test.js +142 -0
- package/lib/openzeppelin-contracts/test/token/ERC20/utils/SafeERC20.test.js +463 -0
- package/lib/openzeppelin-contracts/test/token/ERC6909/ERC6909.behavior.js +216 -0
- package/lib/openzeppelin-contracts/test/token/ERC6909/ERC6909.test.js +104 -0
- package/lib/openzeppelin-contracts/test/token/ERC6909/extensions/ERC6909ContentURI.test.js +52 -0
- package/lib/openzeppelin-contracts/test/token/ERC6909/extensions/ERC6909Metadata.test.js +62 -0
- package/lib/openzeppelin-contracts/test/token/ERC6909/extensions/ERC6909TokenSupply.test.js +56 -0
- package/lib/openzeppelin-contracts/test/token/ERC721/ERC721.behavior.js +954 -0
- package/lib/openzeppelin-contracts/test/token/ERC721/ERC721.test.js +23 -0
- package/lib/openzeppelin-contracts/test/token/ERC721/ERC721Enumerable.test.js +28 -0
- package/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Burnable.test.js +77 -0
- package/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Consecutive.t.sol +187 -0
- package/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Consecutive.test.js +228 -0
- package/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Pausable.test.js +81 -0
- package/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Royalty.test.js +57 -0
- package/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721URIStorage.test.js +134 -0
- package/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Votes.test.js +194 -0
- package/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Wrapper.test.js +201 -0
- package/lib/openzeppelin-contracts/test/token/ERC721/utils/ERC721Holder.test.js +20 -0
- package/lib/openzeppelin-contracts/test/token/ERC721/utils/ERC721Utils.test.js +94 -0
- package/lib/openzeppelin-contracts/test/token/common/ERC2981.behavior.js +152 -0
- package/lib/openzeppelin-contracts/test/utils/Address.test.js +332 -0
- package/lib/openzeppelin-contracts/test/utils/Arrays.t.sol +416 -0
- package/lib/openzeppelin-contracts/test/utils/Arrays.test.js +284 -0
- package/lib/openzeppelin-contracts/test/utils/Base58.t.sol +24 -0
- package/lib/openzeppelin-contracts/test/utils/Base58.test.js +65 -0
- package/lib/openzeppelin-contracts/test/utils/Base64.t.sol +36 -0
- package/lib/openzeppelin-contracts/test/utils/Base64.test.js +79 -0
- package/lib/openzeppelin-contracts/test/utils/Blockhash.t.sol +101 -0
- package/lib/openzeppelin-contracts/test/utils/Blockhash.test.js +59 -0
- package/lib/openzeppelin-contracts/test/utils/Bytes.t.sol +322 -0
- package/lib/openzeppelin-contracts/test/utils/Bytes.test.js +371 -0
- package/lib/openzeppelin-contracts/test/utils/CAIP.test.js +56 -0
- package/lib/openzeppelin-contracts/test/utils/Calldata.test.js +22 -0
- package/lib/openzeppelin-contracts/test/utils/Context.behavior.js +48 -0
- package/lib/openzeppelin-contracts/test/utils/Context.test.js +18 -0
- package/lib/openzeppelin-contracts/test/utils/Create2.t.sol +17 -0
- package/lib/openzeppelin-contracts/test/utils/Create2.test.js +190 -0
- package/lib/openzeppelin-contracts/test/utils/LowLevelCall.test.js +257 -0
- package/lib/openzeppelin-contracts/test/utils/Memory.t.sol +63 -0
- package/lib/openzeppelin-contracts/test/utils/Memory.test.js +106 -0
- package/lib/openzeppelin-contracts/test/utils/Multicall.test.js +72 -0
- package/lib/openzeppelin-contracts/test/utils/Nonces.behavior.js +189 -0
- package/lib/openzeppelin-contracts/test/utils/Nonces.test.js +16 -0
- package/lib/openzeppelin-contracts/test/utils/NoncesKeyed.t.sol +51 -0
- package/lib/openzeppelin-contracts/test/utils/NoncesKeyed.test.js +17 -0
- package/lib/openzeppelin-contracts/test/utils/Packing.t.sol +993 -0
- package/lib/openzeppelin-contracts/test/utils/Packing.test.js +70 -0
- package/lib/openzeppelin-contracts/test/utils/Panic.test.js +37 -0
- package/lib/openzeppelin-contracts/test/utils/Pausable.test.js +90 -0
- package/lib/openzeppelin-contracts/test/utils/RLP.t.sol +144 -0
- package/lib/openzeppelin-contracts/test/utils/RLP.test.js +224 -0
- package/lib/openzeppelin-contracts/test/utils/ReentrancyGuard.test.js +58 -0
- package/lib/openzeppelin-contracts/test/utils/RelayedCall.test.js +217 -0
- package/lib/openzeppelin-contracts/test/utils/ShortStrings.t.sol +109 -0
- package/lib/openzeppelin-contracts/test/utils/ShortStrings.test.js +64 -0
- package/lib/openzeppelin-contracts/test/utils/SlotDerivation.t.sol +248 -0
- package/lib/openzeppelin-contracts/test/utils/SlotDerivation.test.js +58 -0
- package/lib/openzeppelin-contracts/test/utils/StorageSlot.test.js +73 -0
- package/lib/openzeppelin-contracts/test/utils/Strings.t.sol +50 -0
- package/lib/openzeppelin-contracts/test/utils/Strings.test.js +360 -0
- package/lib/openzeppelin-contracts/test/utils/TransientSlot.test.js +59 -0
- package/lib/openzeppelin-contracts/test/utils/cryptography/ECDSA.test.js +322 -0
- package/lib/openzeppelin-contracts/test/utils/cryptography/EIP712.test.js +105 -0
- package/lib/openzeppelin-contracts/test/utils/cryptography/ERC1271.behavior.js +111 -0
- package/lib/openzeppelin-contracts/test/utils/cryptography/ERC7739.test.js +42 -0
- package/lib/openzeppelin-contracts/test/utils/cryptography/ERC7739Utils.test.js +203 -0
- package/lib/openzeppelin-contracts/test/utils/cryptography/MerkleProof.test.js +216 -0
- package/lib/openzeppelin-contracts/test/utils/cryptography/MessageHashUtils.t.sol +33 -0
- package/lib/openzeppelin-contracts/test/utils/cryptography/MessageHashUtils.test.js +149 -0
- package/lib/openzeppelin-contracts/test/utils/cryptography/P256.t.sol +45 -0
- package/lib/openzeppelin-contracts/test/utils/cryptography/P256.test.js +182 -0
- package/lib/openzeppelin-contracts/test/utils/cryptography/RSA.helper.js +17 -0
- package/lib/openzeppelin-contracts/test/utils/cryptography/RSA.test.js +102 -0
- package/lib/openzeppelin-contracts/test/utils/cryptography/SigVer15_186-3.rsp +3850 -0
- package/lib/openzeppelin-contracts/test/utils/cryptography/SignatureChecker.test.js +427 -0
- package/lib/openzeppelin-contracts/test/utils/cryptography/TrieProof.test.js +659 -0
- package/lib/openzeppelin-contracts/test/utils/cryptography/WebAuthn.t.sol +298 -0
- package/lib/openzeppelin-contracts/test/utils/cryptography/ecdsa_secp256r1_sha256_p1363_test.json +3719 -0
- package/lib/openzeppelin-contracts/test/utils/draft-InteroperableAddress.t.sol +99 -0
- package/lib/openzeppelin-contracts/test/utils/draft-InteroperableAddress.test.js +170 -0
- package/lib/openzeppelin-contracts/test/utils/introspection/ERC165.test.js +18 -0
- package/lib/openzeppelin-contracts/test/utils/introspection/ERC165Checker.test.js +272 -0
- package/lib/openzeppelin-contracts/test/utils/introspection/SupportsInterface.behavior.js +169 -0
- package/lib/openzeppelin-contracts/test/utils/math/Math.t.sol +370 -0
- package/lib/openzeppelin-contracts/test/utils/math/Math.test.js +746 -0
- package/lib/openzeppelin-contracts/test/utils/math/SafeCast.test.js +159 -0
- package/lib/openzeppelin-contracts/test/utils/math/SignedMath.t.sol +81 -0
- package/lib/openzeppelin-contracts/test/utils/math/SignedMath.test.js +53 -0
- package/lib/openzeppelin-contracts/test/utils/structs/Accumulators.t.sol +35 -0
- package/lib/openzeppelin-contracts/test/utils/structs/BitMap.test.js +149 -0
- package/lib/openzeppelin-contracts/test/utils/structs/Checkpoints.t.sol +440 -0
- package/lib/openzeppelin-contracts/test/utils/structs/Checkpoints.test.js +147 -0
- package/lib/openzeppelin-contracts/test/utils/structs/CircularBuffer.test.js +83 -0
- package/lib/openzeppelin-contracts/test/utils/structs/DoubleEndedQueue.test.js +144 -0
- package/lib/openzeppelin-contracts/test/utils/structs/EnumerableMap.behavior.js +214 -0
- package/lib/openzeppelin-contracts/test/utils/structs/EnumerableMap.test.js +83 -0
- package/lib/openzeppelin-contracts/test/utils/structs/EnumerableSet.behavior.js +175 -0
- package/lib/openzeppelin-contracts/test/utils/structs/EnumerableSet.test.js +66 -0
- package/lib/openzeppelin-contracts/test/utils/structs/Heap.t.sol +74 -0
- package/lib/openzeppelin-contracts/test/utils/structs/Heap.test.js +113 -0
- package/lib/openzeppelin-contracts/test/utils/structs/MerkleTree.test.js +180 -0
- package/lib/openzeppelin-contracts/test/utils/types/Time.test.js +135 -0
- package/lucro.txt +1 -0
- package/out/Base.sol/CommonBase.json +1 -0
- package/out/Base.sol/ScriptBase.json +1 -0
- package/out/Base.sol/TestBase.json +1 -0
- package/out/Context.sol/Context.json +1 -0
- package/out/Counter.s.sol/CounterScript.json +1 -0
- package/out/Counter.sol/Counter.json +1 -0
- package/out/Counter.t.sol/CounterTest.json +1 -0
- package/out/ERC20.sol/ERC20.json +1 -0
- package/out/GbitToken.sol/GbitToken.json +1 -0
- package/out/Guestbook.sol/Guestbook.json +1 -0
- package/out/IERC20.sol/IERC20.json +1 -0
- package/out/IERC20Metadata.sol/IERC20Metadata.json +1 -0
- package/out/IMulticall3.sol/IMulticall3.json +1 -0
- package/out/Script.sol/Script.json +1 -0
- package/out/StdAssertions.sol/StdAssertions.json +1 -0
- package/out/StdChains.sol/StdChains.json +1 -0
- package/out/StdCheats.sol/StdCheats.json +1 -0
- package/out/StdCheats.sol/StdCheatsSafe.json +1 -0
- package/out/StdConstants.sol/StdConstants.json +1 -0
- package/out/StdError.sol/stdError.json +1 -0
- package/out/StdInvariant.sol/StdInvariant.json +1 -0
- package/out/StdJson.sol/stdJson.json +1 -0
- package/out/StdMath.sol/stdMath.json +1 -0
- package/out/StdStorage.sol/stdStorage.json +1 -0
- package/out/StdStorage.sol/stdStorageSafe.json +1 -0
- package/out/StdStyle.sol/StdStyle.json +1 -0
- package/out/StdToml.sol/stdToml.json +1 -0
- package/out/StdUtils.sol/StdUtils.json +1 -0
- package/out/Test.sol/Test.json +1 -0
- package/out/Vm.sol/Vm.json +1 -0
- package/out/Vm.sol/VmSafe.json +1 -0
- package/out/Web3HubCore.sol/Web3HubCore.json +1 -0
- package/out/build-info/8a1d781106536b7b.json +1 -0
- package/out/build-info/aac4797350a36a99.json +1 -0
- package/out/build-info/c34d5a7881e6beba.json +1 -0
- package/out/build-info/ce38d811b8078146.json +1 -0
- package/out/build-info/db34a3531e47e196.json +1 -0
- package/out/console.sol/console.json +1 -0
- package/out/draft-IERC6093.sol/IERC1155Errors.json +1 -0
- package/out/draft-IERC6093.sol/IERC20Errors.json +1 -0
- package/out/draft-IERC6093.sol/IERC721Errors.json +1 -0
- package/out/safeconsole.sol/safeconsole.json +1 -0
- package/package.json +25 -0
- package/remappings.txt +1 -0
- package/script/Counter.s.sol +19 -0
- package/src/Counter.sol +14 -0
- package/src/GbitToken.sol +72 -0
- package/src/Guestbook.sol +28 -0
- package/src/Web3HubCore.sol +42 -0
- package/test/Counter.t.sol +24 -0
|
@@ -0,0 +1,2489 @@
|
|
|
1
|
+
const { ethers } = require('hardhat');
|
|
2
|
+
const { expect } = require('chai');
|
|
3
|
+
const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
|
|
4
|
+
|
|
5
|
+
const { impersonate } = require('../../helpers/account');
|
|
6
|
+
const { MAX_UINT48 } = require('../../helpers/constants');
|
|
7
|
+
const { selector } = require('../../helpers/methods');
|
|
8
|
+
const time = require('../../helpers/time');
|
|
9
|
+
|
|
10
|
+
const {
|
|
11
|
+
buildBaseRoles,
|
|
12
|
+
formatAccess,
|
|
13
|
+
EXPIRATION,
|
|
14
|
+
MINSETBACK,
|
|
15
|
+
EXECUTION_ID_STORAGE_SLOT,
|
|
16
|
+
CONSUMING_SCHEDULE_STORAGE_SLOT,
|
|
17
|
+
prepareOperation,
|
|
18
|
+
hashOperation,
|
|
19
|
+
} = require('../../helpers/access-manager');
|
|
20
|
+
|
|
21
|
+
const {
|
|
22
|
+
shouldBehaveLikeDelayedAdminOperation,
|
|
23
|
+
shouldBehaveLikeNotDelayedAdminOperation,
|
|
24
|
+
shouldBehaveLikeRoleAdminOperation,
|
|
25
|
+
shouldBehaveLikeAManagedRestrictedOperation,
|
|
26
|
+
shouldBehaveLikeASelfRestrictedOperation,
|
|
27
|
+
} = require('./AccessManager.behavior');
|
|
28
|
+
|
|
29
|
+
const {
|
|
30
|
+
LIKE_COMMON_SCHEDULABLE,
|
|
31
|
+
testAsClosable,
|
|
32
|
+
testAsDelay,
|
|
33
|
+
testAsSchedulableOperation,
|
|
34
|
+
testAsCanCall,
|
|
35
|
+
testAsHasRole,
|
|
36
|
+
testAsGetAccess,
|
|
37
|
+
} = require('./AccessManager.predicate');
|
|
38
|
+
|
|
39
|
+
async function fixture() {
|
|
40
|
+
const [admin, roleAdmin, roleGuardian, member, user, other] = await ethers.getSigners();
|
|
41
|
+
|
|
42
|
+
// Build roles
|
|
43
|
+
const roles = buildBaseRoles();
|
|
44
|
+
|
|
45
|
+
// Add members
|
|
46
|
+
roles.ADMIN.members = [admin];
|
|
47
|
+
roles.SOME_ADMIN.members = [roleAdmin];
|
|
48
|
+
roles.SOME_GUARDIAN.members = [roleGuardian];
|
|
49
|
+
roles.SOME.members = [member];
|
|
50
|
+
roles.PUBLIC.members = [admin, roleAdmin, roleGuardian, member, user, other];
|
|
51
|
+
|
|
52
|
+
const manager = await ethers.deployContract('$AccessManagerMock', [admin]);
|
|
53
|
+
const target = await ethers.deployContract('$AccessManagedTarget', [manager]);
|
|
54
|
+
|
|
55
|
+
for (const { id: roleId, admin, guardian, members } of Object.values(roles)) {
|
|
56
|
+
if (roleId === roles.PUBLIC.id) continue; // Every address belong to public and is locked
|
|
57
|
+
if (roleId === roles.ADMIN.id) continue; // Admin set during construction and is locked
|
|
58
|
+
|
|
59
|
+
// Set admin role avoiding default
|
|
60
|
+
if (admin.id !== roles.ADMIN.id) {
|
|
61
|
+
await manager.$_setRoleAdmin(roleId, admin.id);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Set guardian role avoiding default
|
|
65
|
+
if (guardian.id !== roles.ADMIN.id) {
|
|
66
|
+
await manager.$_setRoleGuardian(roleId, guardian.id);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Grant role to members
|
|
70
|
+
for (const member of members) {
|
|
71
|
+
await manager.$_grantRole(roleId, member, 0, 0);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
admin,
|
|
77
|
+
roleAdmin,
|
|
78
|
+
user,
|
|
79
|
+
other,
|
|
80
|
+
roles,
|
|
81
|
+
manager,
|
|
82
|
+
target,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// This test suite is made using the following tools:
|
|
87
|
+
//
|
|
88
|
+
// * Predicates: Functions with common conditional setups without assertions.
|
|
89
|
+
// * Behaviors: Functions with common assertions.
|
|
90
|
+
//
|
|
91
|
+
// The behavioral tests are built by composing predicates and are used as templates
|
|
92
|
+
// for testing access to restricted functions.
|
|
93
|
+
//
|
|
94
|
+
// Similarly, unit tests in this suite will use predicates to test subsets of these
|
|
95
|
+
// behaviors and are helped by common assertions provided for some of the predicates.
|
|
96
|
+
//
|
|
97
|
+
// The predicates can be identified by the `testAs*` prefix while the behaviors
|
|
98
|
+
// are prefixed with `shouldBehave*`. The common assertions for predicates are
|
|
99
|
+
// defined as constants.
|
|
100
|
+
describe('AccessManager', function () {
|
|
101
|
+
beforeEach(async function () {
|
|
102
|
+
Object.assign(this, await loadFixture(fixture));
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
describe('during construction', function () {
|
|
106
|
+
it('grants admin role to initialAdmin', async function () {
|
|
107
|
+
const manager = await ethers.deployContract('$AccessManager', [this.other]);
|
|
108
|
+
expect(await manager.hasRole(this.roles.ADMIN.id, this.other).then(formatAccess)).to.be.deep.equal([true, '0']);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('rejects zero address for initialAdmin', async function () {
|
|
112
|
+
await expect(ethers.deployContract('$AccessManager', [ethers.ZeroAddress]))
|
|
113
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerInvalidInitialAdmin')
|
|
114
|
+
.withArgs(ethers.ZeroAddress);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('initializes setup roles correctly', async function () {
|
|
118
|
+
for (const { id: roleId, admin, guardian, members } of Object.values(this.roles)) {
|
|
119
|
+
expect(await this.manager.getRoleAdmin(roleId)).to.equal(admin.id);
|
|
120
|
+
expect(await this.manager.getRoleGuardian(roleId)).to.equal(guardian.id);
|
|
121
|
+
|
|
122
|
+
for (const user of this.roles.PUBLIC.members) {
|
|
123
|
+
expect(await this.manager.hasRole(roleId, user).then(formatAccess)).to.be.deep.equal([
|
|
124
|
+
members.includes(user),
|
|
125
|
+
'0',
|
|
126
|
+
]);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
describe('getters', function () {
|
|
133
|
+
describe('#canCall', function () {
|
|
134
|
+
beforeEach('set calldata', function () {
|
|
135
|
+
this.calldata = '0x12345678';
|
|
136
|
+
this.role = { id: 379204n };
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
testAsCanCall({
|
|
140
|
+
closed() {
|
|
141
|
+
it('should return false and no delay', async function () {
|
|
142
|
+
const { immediate, delay } = await this.manager.canCall(
|
|
143
|
+
this.other,
|
|
144
|
+
this.target,
|
|
145
|
+
this.calldata.substring(0, 10),
|
|
146
|
+
);
|
|
147
|
+
expect(immediate).to.be.false;
|
|
148
|
+
expect(delay).to.equal(0n);
|
|
149
|
+
});
|
|
150
|
+
},
|
|
151
|
+
open: {
|
|
152
|
+
callerIsTheManager: {
|
|
153
|
+
executing() {
|
|
154
|
+
it('should return true and no delay', async function () {
|
|
155
|
+
const { immediate, delay } = await this.manager.canCall(
|
|
156
|
+
this.caller,
|
|
157
|
+
this.target,
|
|
158
|
+
this.calldata.substring(0, 10),
|
|
159
|
+
);
|
|
160
|
+
expect(immediate).to.be.true;
|
|
161
|
+
expect(delay).to.equal(0n);
|
|
162
|
+
});
|
|
163
|
+
},
|
|
164
|
+
notExecuting() {
|
|
165
|
+
it('should return false and no delay', async function () {
|
|
166
|
+
const { immediate, delay } = await this.manager.canCall(
|
|
167
|
+
this.caller,
|
|
168
|
+
this.target,
|
|
169
|
+
this.calldata.substring(0, 10),
|
|
170
|
+
);
|
|
171
|
+
expect(immediate).to.be.false;
|
|
172
|
+
expect(delay).to.equal(0n);
|
|
173
|
+
});
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
callerIsNotTheManager: {
|
|
177
|
+
publicRoleIsRequired() {
|
|
178
|
+
it('should return true and no delay', async function () {
|
|
179
|
+
const { immediate, delay } = await this.manager.canCall(
|
|
180
|
+
this.caller,
|
|
181
|
+
this.target,
|
|
182
|
+
this.calldata.substring(0, 10),
|
|
183
|
+
);
|
|
184
|
+
expect(immediate).to.be.true;
|
|
185
|
+
expect(delay).to.equal(0n);
|
|
186
|
+
});
|
|
187
|
+
},
|
|
188
|
+
specificRoleIsRequired: {
|
|
189
|
+
requiredRoleIsGranted: {
|
|
190
|
+
roleGrantingIsDelayed: {
|
|
191
|
+
callerHasAnExecutionDelay: {
|
|
192
|
+
beforeGrantDelay: function self() {
|
|
193
|
+
self.mineDelay = true;
|
|
194
|
+
|
|
195
|
+
it('should return false and no execution delay', async function () {
|
|
196
|
+
const { immediate, delay } = await this.manager.canCall(
|
|
197
|
+
this.caller,
|
|
198
|
+
this.target,
|
|
199
|
+
this.calldata.substring(0, 10),
|
|
200
|
+
);
|
|
201
|
+
expect(immediate).to.be.false;
|
|
202
|
+
expect(delay).to.equal(0n);
|
|
203
|
+
});
|
|
204
|
+
},
|
|
205
|
+
afterGrantDelay: function self() {
|
|
206
|
+
self.mineDelay = true;
|
|
207
|
+
|
|
208
|
+
beforeEach('sets execution delay', function () {
|
|
209
|
+
this.scheduleIn = this.executionDelay; // For testAsSchedulableOperation
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
testAsSchedulableOperation({
|
|
213
|
+
scheduled: {
|
|
214
|
+
before: function self() {
|
|
215
|
+
self.mineDelay = true;
|
|
216
|
+
|
|
217
|
+
it('should return false and execution delay', async function () {
|
|
218
|
+
const { immediate, delay } = await this.manager.canCall(
|
|
219
|
+
this.caller,
|
|
220
|
+
this.target,
|
|
221
|
+
this.calldata.substring(0, 10),
|
|
222
|
+
);
|
|
223
|
+
expect(immediate).to.be.false;
|
|
224
|
+
expect(delay).to.equal(this.executionDelay);
|
|
225
|
+
});
|
|
226
|
+
},
|
|
227
|
+
after: function self() {
|
|
228
|
+
self.mineDelay = true;
|
|
229
|
+
|
|
230
|
+
it('should return false and execution delay', async function () {
|
|
231
|
+
const { immediate, delay } = await this.manager.canCall(
|
|
232
|
+
this.caller,
|
|
233
|
+
this.target,
|
|
234
|
+
this.calldata.substring(0, 10),
|
|
235
|
+
);
|
|
236
|
+
expect(immediate).to.be.false;
|
|
237
|
+
expect(delay).to.equal(this.executionDelay);
|
|
238
|
+
});
|
|
239
|
+
},
|
|
240
|
+
expired: function self() {
|
|
241
|
+
self.mineDelay = true;
|
|
242
|
+
|
|
243
|
+
it('should return false and execution delay', async function () {
|
|
244
|
+
const { immediate, delay } = await this.manager.canCall(
|
|
245
|
+
this.caller,
|
|
246
|
+
this.target,
|
|
247
|
+
this.calldata.substring(0, 10),
|
|
248
|
+
);
|
|
249
|
+
expect(immediate).to.be.false;
|
|
250
|
+
expect(delay).to.equal(this.executionDelay);
|
|
251
|
+
});
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
notScheduled() {
|
|
255
|
+
it('should return false and execution delay', async function () {
|
|
256
|
+
const { immediate, delay } = await this.manager.canCall(
|
|
257
|
+
this.caller,
|
|
258
|
+
this.target,
|
|
259
|
+
this.calldata.substring(0, 10),
|
|
260
|
+
);
|
|
261
|
+
expect(immediate).to.be.false;
|
|
262
|
+
expect(delay).to.equal(this.executionDelay);
|
|
263
|
+
});
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
callerHasNoExecutionDelay: {
|
|
269
|
+
beforeGrantDelay: function self() {
|
|
270
|
+
self.mineDelay = true;
|
|
271
|
+
|
|
272
|
+
it('should return false and no execution delay', async function () {
|
|
273
|
+
const { immediate, delay } = await this.manager.canCall(
|
|
274
|
+
this.caller,
|
|
275
|
+
this.target,
|
|
276
|
+
this.calldata.substring(0, 10),
|
|
277
|
+
);
|
|
278
|
+
expect(immediate).to.be.false;
|
|
279
|
+
expect(delay).to.equal(0n);
|
|
280
|
+
});
|
|
281
|
+
},
|
|
282
|
+
afterGrantDelay: function self() {
|
|
283
|
+
self.mineDelay = true;
|
|
284
|
+
|
|
285
|
+
it('should return true and no execution delay', async function () {
|
|
286
|
+
const { immediate, delay } = await this.manager.canCall(
|
|
287
|
+
this.caller,
|
|
288
|
+
this.target,
|
|
289
|
+
this.calldata.substring(0, 10),
|
|
290
|
+
);
|
|
291
|
+
expect(immediate).to.be.true;
|
|
292
|
+
expect(delay).to.equal(0n);
|
|
293
|
+
});
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
roleGrantingIsNotDelayed: {
|
|
298
|
+
callerHasAnExecutionDelay() {
|
|
299
|
+
it('should return false and execution delay', async function () {
|
|
300
|
+
const { immediate, delay } = await this.manager.canCall(
|
|
301
|
+
this.caller,
|
|
302
|
+
this.target,
|
|
303
|
+
this.calldata.substring(0, 10),
|
|
304
|
+
);
|
|
305
|
+
expect(immediate).to.be.false;
|
|
306
|
+
expect(delay).to.equal(this.executionDelay);
|
|
307
|
+
});
|
|
308
|
+
},
|
|
309
|
+
callerHasNoExecutionDelay() {
|
|
310
|
+
it('should return true and no execution delay', async function () {
|
|
311
|
+
const { immediate, delay } = await this.manager.canCall(
|
|
312
|
+
this.caller,
|
|
313
|
+
this.target,
|
|
314
|
+
this.calldata.substring(0, 10),
|
|
315
|
+
);
|
|
316
|
+
expect(immediate).to.be.true;
|
|
317
|
+
expect(delay).to.equal(0n);
|
|
318
|
+
});
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
},
|
|
322
|
+
requiredRoleIsNotGranted() {
|
|
323
|
+
it('should return false and no execution delay', async function () {
|
|
324
|
+
const { immediate, delay } = await this.manager.canCall(
|
|
325
|
+
this.caller,
|
|
326
|
+
this.target,
|
|
327
|
+
this.calldata.substring(0, 10),
|
|
328
|
+
);
|
|
329
|
+
expect(immediate).to.be.false;
|
|
330
|
+
expect(delay).to.equal(0n);
|
|
331
|
+
});
|
|
332
|
+
},
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
describe('#expiration', function () {
|
|
340
|
+
it('has a 7 days default expiration', async function () {
|
|
341
|
+
expect(await this.manager.expiration()).to.equal(EXPIRATION);
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
describe('#minSetback', function () {
|
|
346
|
+
it('has a 5 days default minimum setback', async function () {
|
|
347
|
+
expect(await this.manager.minSetback()).to.equal(MINSETBACK);
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
describe('#isTargetClosed', function () {
|
|
352
|
+
testAsClosable({
|
|
353
|
+
closed() {
|
|
354
|
+
it('returns true', async function () {
|
|
355
|
+
expect(await this.manager.isTargetClosed(this.target)).to.be.true;
|
|
356
|
+
});
|
|
357
|
+
},
|
|
358
|
+
open() {
|
|
359
|
+
it('returns false', async function () {
|
|
360
|
+
expect(await this.manager.isTargetClosed(this.target)).to.be.false;
|
|
361
|
+
});
|
|
362
|
+
},
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
describe('#getTargetFunctionRole', function () {
|
|
367
|
+
const methodSelector = selector('something(address,bytes)');
|
|
368
|
+
|
|
369
|
+
it('returns the target function role', async function () {
|
|
370
|
+
const roleId = 21498n;
|
|
371
|
+
await this.manager.$_setTargetFunctionRole(this.target, methodSelector, roleId);
|
|
372
|
+
|
|
373
|
+
expect(await this.manager.getTargetFunctionRole(this.target, methodSelector)).to.equal(roleId);
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
it('returns the ADMIN role if not set', async function () {
|
|
377
|
+
expect(await this.manager.getTargetFunctionRole(this.target, methodSelector)).to.equal(this.roles.ADMIN.id);
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
describe('#getTargetAdminDelay', function () {
|
|
382
|
+
describe('when the target admin delay is setup', function () {
|
|
383
|
+
beforeEach('set target admin delay', async function () {
|
|
384
|
+
this.oldDelay = await this.manager.getTargetAdminDelay(this.target);
|
|
385
|
+
this.newDelay = time.duration.days(10);
|
|
386
|
+
|
|
387
|
+
await this.manager.$_setTargetAdminDelay(this.target, this.newDelay);
|
|
388
|
+
this.delay = MINSETBACK; // For testAsDelay
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
testAsDelay('effect', {
|
|
392
|
+
before: function self() {
|
|
393
|
+
self.mineDelay = true;
|
|
394
|
+
|
|
395
|
+
it('returns the old target admin delay', async function () {
|
|
396
|
+
expect(await this.manager.getTargetAdminDelay(this.target)).to.equal(this.oldDelay);
|
|
397
|
+
});
|
|
398
|
+
},
|
|
399
|
+
after: function self() {
|
|
400
|
+
self.mineDelay = true;
|
|
401
|
+
|
|
402
|
+
it('returns the new target admin delay', async function () {
|
|
403
|
+
expect(await this.manager.getTargetAdminDelay(this.target)).to.equal(this.newDelay);
|
|
404
|
+
});
|
|
405
|
+
},
|
|
406
|
+
});
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
it('returns the 0 if not set', async function () {
|
|
410
|
+
expect(await this.manager.getTargetAdminDelay(this.target)).to.equal(0n);
|
|
411
|
+
});
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
describe('#getRoleAdmin', function () {
|
|
415
|
+
const roleId = 5234907n;
|
|
416
|
+
|
|
417
|
+
it('returns the role admin', async function () {
|
|
418
|
+
const adminId = 789433n;
|
|
419
|
+
|
|
420
|
+
await this.manager.$_setRoleAdmin(roleId, adminId);
|
|
421
|
+
|
|
422
|
+
expect(await this.manager.getRoleAdmin(roleId)).to.equal(adminId);
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
it('returns the ADMIN role if not set', async function () {
|
|
426
|
+
expect(await this.manager.getRoleAdmin(roleId)).to.equal(this.roles.ADMIN.id);
|
|
427
|
+
});
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
describe('#getRoleGuardian', function () {
|
|
431
|
+
const roleId = 5234907n;
|
|
432
|
+
|
|
433
|
+
it('returns the role guardian', async function () {
|
|
434
|
+
const guardianId = 789433n;
|
|
435
|
+
|
|
436
|
+
await this.manager.$_setRoleGuardian(roleId, guardianId);
|
|
437
|
+
|
|
438
|
+
expect(await this.manager.getRoleGuardian(roleId)).to.equal(guardianId);
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
it('returns the ADMIN role if not set', async function () {
|
|
442
|
+
expect(await this.manager.getRoleGuardian(roleId)).to.equal(this.roles.ADMIN.id);
|
|
443
|
+
});
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
describe('#getRoleGrantDelay', function () {
|
|
447
|
+
const roleId = 9248439n;
|
|
448
|
+
|
|
449
|
+
describe('when the grant admin delay is setup', function () {
|
|
450
|
+
beforeEach('set grant admin delay', async function () {
|
|
451
|
+
this.oldDelay = await this.manager.getRoleGrantDelay(roleId);
|
|
452
|
+
this.newDelay = time.duration.days(11);
|
|
453
|
+
|
|
454
|
+
await this.manager.$_setGrantDelay(roleId, this.newDelay);
|
|
455
|
+
this.delay = MINSETBACK; // For testAsDelay
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
testAsDelay('grant', {
|
|
459
|
+
before: function self() {
|
|
460
|
+
self.mineDelay = true;
|
|
461
|
+
|
|
462
|
+
it('returns the old role grant delay', async function () {
|
|
463
|
+
expect(await this.manager.getRoleGrantDelay(roleId)).to.equal(this.oldDelay);
|
|
464
|
+
});
|
|
465
|
+
},
|
|
466
|
+
after: function self() {
|
|
467
|
+
self.mineDelay = true;
|
|
468
|
+
|
|
469
|
+
it('returns the new role grant delay', async function () {
|
|
470
|
+
expect(await this.manager.getRoleGrantDelay(roleId)).to.equal(this.newDelay);
|
|
471
|
+
});
|
|
472
|
+
},
|
|
473
|
+
});
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
it('returns 0 if delay is not set', async function () {
|
|
477
|
+
expect(await this.manager.getTargetAdminDelay(this.target)).to.equal(0n);
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
describe('#getAccess', function () {
|
|
482
|
+
beforeEach('set role', function () {
|
|
483
|
+
this.role = { id: 9452n };
|
|
484
|
+
this.caller = this.user;
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
testAsGetAccess({
|
|
488
|
+
requiredRoleIsGranted: {
|
|
489
|
+
roleGrantingIsDelayed: {
|
|
490
|
+
callerHasAnExecutionDelay: {
|
|
491
|
+
beforeGrantDelay: function self() {
|
|
492
|
+
self.mineDelay = true;
|
|
493
|
+
|
|
494
|
+
it('role is not in effect and execution delay is set', async function () {
|
|
495
|
+
const access = await this.manager.getAccess(this.role.id, this.caller);
|
|
496
|
+
expect(access[0]).to.equal(this.delayEffect); // inEffectSince
|
|
497
|
+
expect(access[1]).to.equal(this.executionDelay); // currentDelay
|
|
498
|
+
expect(access[2]).to.equal(0n); // pendingDelay
|
|
499
|
+
expect(access[3]).to.equal(0n); // pendingDelayEffect
|
|
500
|
+
|
|
501
|
+
// Not in effect yet
|
|
502
|
+
expect(await time.clock.timestamp()).to.lt(access[0]);
|
|
503
|
+
});
|
|
504
|
+
},
|
|
505
|
+
afterGrantDelay: function self() {
|
|
506
|
+
self.mineDelay = true;
|
|
507
|
+
|
|
508
|
+
it('access has role in effect and execution delay is set', async function () {
|
|
509
|
+
const access = await this.manager.getAccess(this.role.id, this.caller);
|
|
510
|
+
|
|
511
|
+
expect(access[0]).to.equal(this.delayEffect); // inEffectSince
|
|
512
|
+
expect(access[1]).to.equal(this.executionDelay); // currentDelay
|
|
513
|
+
expect(access[2]).to.equal(0n); // pendingDelay
|
|
514
|
+
expect(access[3]).to.equal(0n); // pendingDelayEffect
|
|
515
|
+
|
|
516
|
+
// Already in effect
|
|
517
|
+
expect(await time.clock.timestamp()).to.equal(access[0]);
|
|
518
|
+
});
|
|
519
|
+
},
|
|
520
|
+
},
|
|
521
|
+
callerHasNoExecutionDelay: {
|
|
522
|
+
beforeGrantDelay: function self() {
|
|
523
|
+
self.mineDelay = true;
|
|
524
|
+
|
|
525
|
+
it('access has role not in effect without execution delay', async function () {
|
|
526
|
+
const access = await this.manager.getAccess(this.role.id, this.caller);
|
|
527
|
+
expect(access[0]).to.equal(this.delayEffect); // inEffectSince
|
|
528
|
+
expect(access[1]).to.equal(0n); // currentDelay
|
|
529
|
+
expect(access[2]).to.equal(0n); // pendingDelay
|
|
530
|
+
expect(access[3]).to.equal(0n); // pendingDelayEffect
|
|
531
|
+
|
|
532
|
+
// Not in effect yet
|
|
533
|
+
expect(await time.clock.timestamp()).to.lt(access[0]);
|
|
534
|
+
});
|
|
535
|
+
},
|
|
536
|
+
afterGrantDelay: function self() {
|
|
537
|
+
self.mineDelay = true;
|
|
538
|
+
|
|
539
|
+
it('role is in effect without execution delay', async function () {
|
|
540
|
+
const access = await this.manager.getAccess(this.role.id, this.caller);
|
|
541
|
+
expect(access[0]).to.equal(this.delayEffect); // inEffectSince
|
|
542
|
+
expect(access[1]).to.equal(0n); // currentDelay
|
|
543
|
+
expect(access[2]).to.equal(0n); // pendingDelay
|
|
544
|
+
expect(access[3]).to.equal(0n); // pendingDelayEffect
|
|
545
|
+
|
|
546
|
+
// Already in effect
|
|
547
|
+
expect(await time.clock.timestamp()).to.equal(access[0]);
|
|
548
|
+
});
|
|
549
|
+
},
|
|
550
|
+
},
|
|
551
|
+
},
|
|
552
|
+
roleGrantingIsNotDelayed: {
|
|
553
|
+
callerHasAnExecutionDelay() {
|
|
554
|
+
it('access has role in effect and execution delay is set', async function () {
|
|
555
|
+
const access = await this.manager.getAccess(this.role.id, this.caller);
|
|
556
|
+
expect(access[0]).to.equal(await time.clock.timestamp()); // inEffectSince
|
|
557
|
+
expect(access[1]).to.equal(this.executionDelay); // currentDelay
|
|
558
|
+
expect(access[2]).to.equal(0n); // pendingDelay
|
|
559
|
+
expect(access[3]).to.equal(0n); // pendingDelayEffect
|
|
560
|
+
|
|
561
|
+
// Already in effect
|
|
562
|
+
expect(await time.clock.timestamp()).to.equal(access[0]);
|
|
563
|
+
});
|
|
564
|
+
},
|
|
565
|
+
callerHasNoExecutionDelay() {
|
|
566
|
+
it('access has role in effect without execution delay', async function () {
|
|
567
|
+
const access = await this.manager.getAccess(this.role.id, this.caller);
|
|
568
|
+
expect(access[0]).to.equal(await time.clock.timestamp()); // inEffectSince
|
|
569
|
+
expect(access[1]).to.equal(0n); // currentDelay
|
|
570
|
+
expect(access[2]).to.equal(0n); // pendingDelay
|
|
571
|
+
expect(access[3]).to.equal(0n); // pendingDelayEffect
|
|
572
|
+
|
|
573
|
+
// Already in effect
|
|
574
|
+
expect(await time.clock.timestamp()).to.equal(access[0]);
|
|
575
|
+
});
|
|
576
|
+
},
|
|
577
|
+
},
|
|
578
|
+
},
|
|
579
|
+
requiredRoleIsNotGranted() {
|
|
580
|
+
it('has empty access', async function () {
|
|
581
|
+
const access = await this.manager.getAccess(this.role.id, this.caller);
|
|
582
|
+
expect(access[0]).to.equal(0n); // inEffectSince
|
|
583
|
+
expect(access[1]).to.equal(0n); // currentDelay
|
|
584
|
+
expect(access[2]).to.equal(0n); // pendingDelay
|
|
585
|
+
expect(access[3]).to.equal(0n); // pendingDelayEffect
|
|
586
|
+
});
|
|
587
|
+
},
|
|
588
|
+
});
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
describe('#hasRole', function () {
|
|
592
|
+
beforeEach('setup testAsHasRole', function () {
|
|
593
|
+
this.role = { id: 49832n };
|
|
594
|
+
this.calldata = '0x12345678';
|
|
595
|
+
this.caller = this.user;
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
testAsHasRole({
|
|
599
|
+
publicRoleIsRequired() {
|
|
600
|
+
it('has PUBLIC role', async function () {
|
|
601
|
+
const { isMember, executionDelay } = await this.manager.hasRole(this.role.id, this.caller);
|
|
602
|
+
expect(isMember).to.be.true;
|
|
603
|
+
expect(executionDelay).to.equal('0');
|
|
604
|
+
});
|
|
605
|
+
},
|
|
606
|
+
specificRoleIsRequired: {
|
|
607
|
+
requiredRoleIsGranted: {
|
|
608
|
+
roleGrantingIsDelayed: {
|
|
609
|
+
callerHasAnExecutionDelay: {
|
|
610
|
+
beforeGrantDelay: function self() {
|
|
611
|
+
self.mineDelay = true;
|
|
612
|
+
|
|
613
|
+
it('does not have role but execution delay', async function () {
|
|
614
|
+
const { isMember, executionDelay } = await this.manager.hasRole(this.role.id, this.caller);
|
|
615
|
+
expect(isMember).to.be.false;
|
|
616
|
+
expect(executionDelay).to.equal(this.executionDelay);
|
|
617
|
+
});
|
|
618
|
+
},
|
|
619
|
+
afterGrantDelay: function self() {
|
|
620
|
+
self.mineDelay = true;
|
|
621
|
+
|
|
622
|
+
it('has role and execution delay', async function () {
|
|
623
|
+
const { isMember, executionDelay } = await this.manager.hasRole(this.role.id, this.caller);
|
|
624
|
+
expect(isMember).to.be.true;
|
|
625
|
+
expect(executionDelay).to.equal(this.executionDelay);
|
|
626
|
+
});
|
|
627
|
+
},
|
|
628
|
+
},
|
|
629
|
+
callerHasNoExecutionDelay: {
|
|
630
|
+
beforeGrantDelay: function self() {
|
|
631
|
+
self.mineDelay = true;
|
|
632
|
+
|
|
633
|
+
it('does not have role nor execution delay', async function () {
|
|
634
|
+
const { isMember, executionDelay } = await this.manager.hasRole(this.role.id, this.caller);
|
|
635
|
+
expect(isMember).to.be.false;
|
|
636
|
+
expect(executionDelay).to.equal('0');
|
|
637
|
+
});
|
|
638
|
+
},
|
|
639
|
+
afterGrantDelay: function self() {
|
|
640
|
+
self.mineDelay = true;
|
|
641
|
+
|
|
642
|
+
it('has role and no execution delay', async function () {
|
|
643
|
+
const { isMember, executionDelay } = await this.manager.hasRole(this.role.id, this.caller);
|
|
644
|
+
expect(isMember).to.be.true;
|
|
645
|
+
expect(executionDelay).to.equal('0');
|
|
646
|
+
});
|
|
647
|
+
},
|
|
648
|
+
},
|
|
649
|
+
},
|
|
650
|
+
roleGrantingIsNotDelayed: {
|
|
651
|
+
callerHasAnExecutionDelay() {
|
|
652
|
+
it('has role and execution delay', async function () {
|
|
653
|
+
const { isMember, executionDelay } = await this.manager.hasRole(this.role.id, this.caller);
|
|
654
|
+
expect(isMember).to.be.true;
|
|
655
|
+
expect(executionDelay).to.equal(this.executionDelay);
|
|
656
|
+
});
|
|
657
|
+
},
|
|
658
|
+
callerHasNoExecutionDelay() {
|
|
659
|
+
it('has role and no execution delay', async function () {
|
|
660
|
+
const { isMember, executionDelay } = await this.manager.hasRole(this.role.id, this.caller);
|
|
661
|
+
expect(isMember).to.be.true;
|
|
662
|
+
expect(executionDelay).to.equal('0');
|
|
663
|
+
});
|
|
664
|
+
},
|
|
665
|
+
},
|
|
666
|
+
},
|
|
667
|
+
requiredRoleIsNotGranted() {
|
|
668
|
+
it('has no role and no execution delay', async function () {
|
|
669
|
+
const { isMember, executionDelay } = await this.manager.hasRole(this.role.id, this.caller);
|
|
670
|
+
expect(isMember).to.be.false;
|
|
671
|
+
expect(executionDelay).to.equal('0');
|
|
672
|
+
});
|
|
673
|
+
},
|
|
674
|
+
},
|
|
675
|
+
});
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
describe('#getSchedule', function () {
|
|
679
|
+
beforeEach('set role and calldata', async function () {
|
|
680
|
+
const fnRestricted = this.target.fnRestricted.getFragment().selector;
|
|
681
|
+
this.caller = this.user;
|
|
682
|
+
this.role = { id: 493590n };
|
|
683
|
+
await this.manager.$_setTargetFunctionRole(this.target, fnRestricted, this.role.id);
|
|
684
|
+
await this.manager.$_grantRole(this.role.id, this.caller, 0, 1); // nonzero execution delay
|
|
685
|
+
|
|
686
|
+
this.calldata = this.target.interface.encodeFunctionData(fnRestricted, []);
|
|
687
|
+
this.scheduleIn = time.duration.days(10); // For testAsSchedulableOperation
|
|
688
|
+
});
|
|
689
|
+
|
|
690
|
+
testAsSchedulableOperation({
|
|
691
|
+
scheduled: {
|
|
692
|
+
before: function self() {
|
|
693
|
+
self.mineDelay = true;
|
|
694
|
+
|
|
695
|
+
it('returns schedule in the future', async function () {
|
|
696
|
+
const schedule = await this.manager.getSchedule(this.operationId);
|
|
697
|
+
expect(schedule).to.equal(this.scheduledAt + this.scheduleIn);
|
|
698
|
+
expect(schedule).to.gt(await time.clock.timestamp());
|
|
699
|
+
});
|
|
700
|
+
},
|
|
701
|
+
after: function self() {
|
|
702
|
+
self.mineDelay = true;
|
|
703
|
+
|
|
704
|
+
it('returns schedule', async function () {
|
|
705
|
+
const schedule = await this.manager.getSchedule(this.operationId);
|
|
706
|
+
expect(schedule).to.equal(this.scheduledAt + this.scheduleIn);
|
|
707
|
+
expect(schedule).to.equal(await time.clock.timestamp());
|
|
708
|
+
});
|
|
709
|
+
},
|
|
710
|
+
expired: function self() {
|
|
711
|
+
self.mineDelay = true;
|
|
712
|
+
|
|
713
|
+
it('returns 0', async function () {
|
|
714
|
+
expect(await this.manager.getSchedule(this.operationId)).to.equal(0n);
|
|
715
|
+
});
|
|
716
|
+
},
|
|
717
|
+
},
|
|
718
|
+
notScheduled() {
|
|
719
|
+
it('defaults to 0', async function () {
|
|
720
|
+
expect(await this.manager.getSchedule(this.operationId)).to.equal(0n);
|
|
721
|
+
});
|
|
722
|
+
},
|
|
723
|
+
});
|
|
724
|
+
});
|
|
725
|
+
|
|
726
|
+
describe('#getNonce', function () {
|
|
727
|
+
describe('when operation is scheduled', function () {
|
|
728
|
+
beforeEach('schedule operation', async function () {
|
|
729
|
+
const fnRestricted = this.target.fnRestricted.getFragment().selector;
|
|
730
|
+
this.caller = this.user;
|
|
731
|
+
this.role = { id: 4209043n };
|
|
732
|
+
await this.manager.$_setTargetFunctionRole(this.target, fnRestricted, this.role.id);
|
|
733
|
+
await this.manager.$_grantRole(this.role.id, this.caller, 0, 1); // nonzero execution delay
|
|
734
|
+
|
|
735
|
+
this.calldata = this.target.interface.encodeFunctionData(fnRestricted, []);
|
|
736
|
+
this.delay = time.duration.days(10);
|
|
737
|
+
|
|
738
|
+
const { operationId, schedule } = await prepareOperation(this.manager, {
|
|
739
|
+
caller: this.caller,
|
|
740
|
+
target: this.target,
|
|
741
|
+
calldata: this.calldata,
|
|
742
|
+
delay: this.delay,
|
|
743
|
+
});
|
|
744
|
+
await schedule();
|
|
745
|
+
this.operationId = operationId;
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
it('returns nonce', async function () {
|
|
749
|
+
expect(await this.manager.getNonce(this.operationId)).to.equal(1n);
|
|
750
|
+
});
|
|
751
|
+
});
|
|
752
|
+
|
|
753
|
+
describe('when is not scheduled', function () {
|
|
754
|
+
it('returns default 0', async function () {
|
|
755
|
+
expect(await this.manager.getNonce(ethers.id('operation'))).to.equal(0n);
|
|
756
|
+
});
|
|
757
|
+
});
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
describe('#hashOperation', function () {
|
|
761
|
+
it('returns an operationId', async function () {
|
|
762
|
+
const args = [this.user, this.other, '0x123543'];
|
|
763
|
+
expect(await this.manager.hashOperation(...args)).to.equal(hashOperation(...args));
|
|
764
|
+
});
|
|
765
|
+
});
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
describe('admin operations', function () {
|
|
769
|
+
beforeEach('set required role', function () {
|
|
770
|
+
this.role = this.roles.ADMIN;
|
|
771
|
+
});
|
|
772
|
+
|
|
773
|
+
describe('subject to a delay', function () {
|
|
774
|
+
describe('#labelRole', function () {
|
|
775
|
+
describe('restrictions', function () {
|
|
776
|
+
beforeEach('set method and args', function () {
|
|
777
|
+
const args = [123443, 'TEST'];
|
|
778
|
+
const method = this.manager.interface.getFunction('labelRole(uint64,string)');
|
|
779
|
+
this.calldata = this.manager.interface.encodeFunctionData(method, args);
|
|
780
|
+
});
|
|
781
|
+
|
|
782
|
+
shouldBehaveLikeDelayedAdminOperation();
|
|
783
|
+
});
|
|
784
|
+
|
|
785
|
+
it('emits an event with the label', async function () {
|
|
786
|
+
await expect(this.manager.connect(this.admin).labelRole(this.roles.SOME.id, 'Some label'))
|
|
787
|
+
.to.emit(this.manager, 'RoleLabel')
|
|
788
|
+
.withArgs(this.roles.SOME.id, 'Some label');
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
it('updates label on a second call', async function () {
|
|
792
|
+
await this.manager.connect(this.admin).labelRole(this.roles.SOME.id, 'Some label');
|
|
793
|
+
|
|
794
|
+
await expect(this.manager.connect(this.admin).labelRole(this.roles.SOME.id, 'Updated label'))
|
|
795
|
+
.to.emit(this.manager, 'RoleLabel')
|
|
796
|
+
.withArgs(this.roles.SOME.id, 'Updated label');
|
|
797
|
+
});
|
|
798
|
+
|
|
799
|
+
it('reverts labeling PUBLIC_ROLE', async function () {
|
|
800
|
+
await expect(this.manager.connect(this.admin).labelRole(this.roles.PUBLIC.id, 'Some label'))
|
|
801
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
|
|
802
|
+
.withArgs(this.roles.PUBLIC.id);
|
|
803
|
+
});
|
|
804
|
+
|
|
805
|
+
it('reverts labeling ADMIN_ROLE', async function () {
|
|
806
|
+
await expect(this.manager.connect(this.admin).labelRole(this.roles.ADMIN.id, 'Some label'))
|
|
807
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
|
|
808
|
+
.withArgs(this.roles.ADMIN.id);
|
|
809
|
+
});
|
|
810
|
+
});
|
|
811
|
+
|
|
812
|
+
describe('#setRoleAdmin', function () {
|
|
813
|
+
describe('restrictions', function () {
|
|
814
|
+
beforeEach('set method and args', function () {
|
|
815
|
+
const args = [93445, 84532];
|
|
816
|
+
const method = this.manager.interface.getFunction('setRoleAdmin(uint64,uint64)');
|
|
817
|
+
this.calldata = this.manager.interface.encodeFunctionData(method, args);
|
|
818
|
+
});
|
|
819
|
+
|
|
820
|
+
shouldBehaveLikeDelayedAdminOperation();
|
|
821
|
+
});
|
|
822
|
+
|
|
823
|
+
it("sets any role's admin if called by an admin", async function () {
|
|
824
|
+
expect(await this.manager.getRoleAdmin(this.roles.SOME.id)).to.equal(this.roles.SOME_ADMIN.id);
|
|
825
|
+
|
|
826
|
+
await expect(this.manager.connect(this.admin).setRoleAdmin(this.roles.SOME.id, this.roles.ADMIN.id))
|
|
827
|
+
.to.emit(this.manager, 'RoleAdminChanged')
|
|
828
|
+
.withArgs(this.roles.SOME.id, this.roles.ADMIN.id);
|
|
829
|
+
|
|
830
|
+
expect(await this.manager.getRoleAdmin(this.roles.SOME.id)).to.equal(this.roles.ADMIN.id);
|
|
831
|
+
});
|
|
832
|
+
|
|
833
|
+
it('reverts setting PUBLIC_ROLE admin', async function () {
|
|
834
|
+
await expect(this.manager.connect(this.admin).setRoleAdmin(this.roles.PUBLIC.id, this.roles.ADMIN.id))
|
|
835
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
|
|
836
|
+
.withArgs(this.roles.PUBLIC.id);
|
|
837
|
+
});
|
|
838
|
+
|
|
839
|
+
it('reverts setting ADMIN_ROLE admin', async function () {
|
|
840
|
+
await expect(this.manager.connect(this.admin).setRoleAdmin(this.roles.ADMIN.id, this.roles.ADMIN.id))
|
|
841
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
|
|
842
|
+
.withArgs(this.roles.ADMIN.id);
|
|
843
|
+
});
|
|
844
|
+
});
|
|
845
|
+
|
|
846
|
+
describe('#setRoleGuardian', function () {
|
|
847
|
+
describe('restrictions', function () {
|
|
848
|
+
beforeEach('set method and args', function () {
|
|
849
|
+
const args = [93445, 84532];
|
|
850
|
+
const method = this.manager.interface.getFunction('setRoleGuardian(uint64,uint64)');
|
|
851
|
+
this.calldata = this.manager.interface.encodeFunctionData(method, args);
|
|
852
|
+
});
|
|
853
|
+
|
|
854
|
+
shouldBehaveLikeDelayedAdminOperation();
|
|
855
|
+
});
|
|
856
|
+
|
|
857
|
+
it("sets any role's guardian if called by an admin", async function () {
|
|
858
|
+
expect(await this.manager.getRoleGuardian(this.roles.SOME.id)).to.equal(this.roles.SOME_GUARDIAN.id);
|
|
859
|
+
|
|
860
|
+
await expect(this.manager.connect(this.admin).setRoleGuardian(this.roles.SOME.id, this.roles.ADMIN.id))
|
|
861
|
+
.to.emit(this.manager, 'RoleGuardianChanged')
|
|
862
|
+
.withArgs(this.roles.SOME.id, this.roles.ADMIN.id);
|
|
863
|
+
|
|
864
|
+
expect(await this.manager.getRoleGuardian(this.roles.SOME.id)).to.equal(this.roles.ADMIN.id);
|
|
865
|
+
});
|
|
866
|
+
|
|
867
|
+
it('reverts setting PUBLIC_ROLE admin', async function () {
|
|
868
|
+
await expect(this.manager.connect(this.admin).setRoleGuardian(this.roles.PUBLIC.id, this.roles.ADMIN.id))
|
|
869
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
|
|
870
|
+
.withArgs(this.roles.PUBLIC.id);
|
|
871
|
+
});
|
|
872
|
+
|
|
873
|
+
it('reverts setting ADMIN_ROLE admin', async function () {
|
|
874
|
+
await expect(this.manager.connect(this.admin).setRoleGuardian(this.roles.ADMIN.id, this.roles.ADMIN.id))
|
|
875
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
|
|
876
|
+
.withArgs(this.roles.ADMIN.id);
|
|
877
|
+
});
|
|
878
|
+
});
|
|
879
|
+
|
|
880
|
+
describe('#setGrantDelay', function () {
|
|
881
|
+
describe('restrictions', function () {
|
|
882
|
+
beforeEach('set method and args', function () {
|
|
883
|
+
const args = [984910, time.duration.days(2)];
|
|
884
|
+
const method = this.manager.interface.getFunction('setGrantDelay(uint64,uint32)');
|
|
885
|
+
this.calldata = this.manager.interface.encodeFunctionData(method, args);
|
|
886
|
+
});
|
|
887
|
+
|
|
888
|
+
shouldBehaveLikeDelayedAdminOperation();
|
|
889
|
+
});
|
|
890
|
+
|
|
891
|
+
it('reverts setting grant delay for the PUBLIC_ROLE', async function () {
|
|
892
|
+
await expect(this.manager.connect(this.admin).setGrantDelay(this.roles.PUBLIC.id, 69n))
|
|
893
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
|
|
894
|
+
.withArgs(this.roles.PUBLIC.id);
|
|
895
|
+
});
|
|
896
|
+
|
|
897
|
+
describe('when increasing the delay', function () {
|
|
898
|
+
const oldDelay = 10n;
|
|
899
|
+
const newDelay = 100n;
|
|
900
|
+
|
|
901
|
+
beforeEach('sets old delay', async function () {
|
|
902
|
+
this.role = this.roles.SOME;
|
|
903
|
+
await this.manager.$_setGrantDelay(this.role.id, oldDelay);
|
|
904
|
+
await time.increaseBy.timestamp(MINSETBACK);
|
|
905
|
+
expect(await this.manager.getRoleGrantDelay(this.role.id)).to.equal(oldDelay);
|
|
906
|
+
});
|
|
907
|
+
|
|
908
|
+
it('increases the delay after minsetback', async function () {
|
|
909
|
+
const txResponse = await this.manager.connect(this.admin).setGrantDelay(this.role.id, newDelay);
|
|
910
|
+
const setGrantDelayAt = await time.clockFromReceipt.timestamp(txResponse);
|
|
911
|
+
await expect(txResponse)
|
|
912
|
+
.to.emit(this.manager, 'RoleGrantDelayChanged')
|
|
913
|
+
.withArgs(this.role.id, newDelay, setGrantDelayAt + MINSETBACK);
|
|
914
|
+
|
|
915
|
+
expect(await this.manager.getRoleGrantDelay(this.role.id)).to.equal(oldDelay);
|
|
916
|
+
await time.increaseBy.timestamp(MINSETBACK);
|
|
917
|
+
expect(await this.manager.getRoleGrantDelay(this.role.id)).to.equal(newDelay);
|
|
918
|
+
});
|
|
919
|
+
});
|
|
920
|
+
|
|
921
|
+
describe('when reducing the delay', function () {
|
|
922
|
+
const oldDelay = time.duration.days(10);
|
|
923
|
+
|
|
924
|
+
beforeEach('sets old delay', async function () {
|
|
925
|
+
this.role = this.roles.SOME;
|
|
926
|
+
await this.manager.$_setGrantDelay(this.role.id, oldDelay);
|
|
927
|
+
await time.increaseBy.timestamp(MINSETBACK);
|
|
928
|
+
expect(await this.manager.getRoleGrantDelay(this.role.id)).to.equal(oldDelay);
|
|
929
|
+
});
|
|
930
|
+
|
|
931
|
+
describe('when the delay difference is shorter than minimum setback', function () {
|
|
932
|
+
const newDelay = oldDelay - 1n;
|
|
933
|
+
|
|
934
|
+
it('increases the delay after minsetback', async function () {
|
|
935
|
+
const txResponse = await this.manager.connect(this.admin).setGrantDelay(this.role.id, newDelay);
|
|
936
|
+
const setGrantDelayAt = await time.clockFromReceipt.timestamp(txResponse);
|
|
937
|
+
await expect(txResponse)
|
|
938
|
+
.to.emit(this.manager, 'RoleGrantDelayChanged')
|
|
939
|
+
.withArgs(this.role.id, newDelay, setGrantDelayAt + MINSETBACK);
|
|
940
|
+
|
|
941
|
+
expect(await this.manager.getRoleGrantDelay(this.role.id)).to.equal(oldDelay);
|
|
942
|
+
await time.increaseBy.timestamp(MINSETBACK);
|
|
943
|
+
expect(await this.manager.getRoleGrantDelay(this.role.id)).to.equal(newDelay);
|
|
944
|
+
});
|
|
945
|
+
});
|
|
946
|
+
|
|
947
|
+
describe('when the delay difference is longer than minimum setback', function () {
|
|
948
|
+
const newDelay = 1n;
|
|
949
|
+
|
|
950
|
+
beforeEach('assert delay difference is higher than minsetback', function () {
|
|
951
|
+
expect(oldDelay - newDelay).to.gt(MINSETBACK);
|
|
952
|
+
});
|
|
953
|
+
|
|
954
|
+
it('increases the delay after delay difference', async function () {
|
|
955
|
+
const setback = oldDelay - newDelay;
|
|
956
|
+
|
|
957
|
+
const txResponse = await this.manager.connect(this.admin).setGrantDelay(this.role.id, newDelay);
|
|
958
|
+
const setGrantDelayAt = await time.clockFromReceipt.timestamp(txResponse);
|
|
959
|
+
|
|
960
|
+
await expect(txResponse)
|
|
961
|
+
.to.emit(this.manager, 'RoleGrantDelayChanged')
|
|
962
|
+
.withArgs(this.role.id, newDelay, setGrantDelayAt + setback);
|
|
963
|
+
|
|
964
|
+
expect(await this.manager.getRoleGrantDelay(this.role.id)).to.equal(oldDelay);
|
|
965
|
+
await time.increaseBy.timestamp(setback);
|
|
966
|
+
expect(await this.manager.getRoleGrantDelay(this.role.id)).to.equal(newDelay);
|
|
967
|
+
});
|
|
968
|
+
});
|
|
969
|
+
});
|
|
970
|
+
});
|
|
971
|
+
|
|
972
|
+
describe('#setTargetAdminDelay', function () {
|
|
973
|
+
describe('restrictions', function () {
|
|
974
|
+
beforeEach('set method and args', function () {
|
|
975
|
+
const args = [this.other.address, time.duration.days(3)];
|
|
976
|
+
const method = this.manager.interface.getFunction('setTargetAdminDelay(address,uint32)');
|
|
977
|
+
this.calldata = this.manager.interface.encodeFunctionData(method, args);
|
|
978
|
+
});
|
|
979
|
+
|
|
980
|
+
shouldBehaveLikeDelayedAdminOperation();
|
|
981
|
+
});
|
|
982
|
+
|
|
983
|
+
describe('when increasing the delay', function () {
|
|
984
|
+
const oldDelay = time.duration.days(10);
|
|
985
|
+
const newDelay = time.duration.days(11);
|
|
986
|
+
|
|
987
|
+
beforeEach('sets old delay', async function () {
|
|
988
|
+
await this.manager.$_setTargetAdminDelay(this.other, oldDelay);
|
|
989
|
+
await time.increaseBy.timestamp(MINSETBACK);
|
|
990
|
+
expect(await this.manager.getTargetAdminDelay(this.other)).to.equal(oldDelay);
|
|
991
|
+
});
|
|
992
|
+
|
|
993
|
+
it('increases the delay after minsetback', async function () {
|
|
994
|
+
const txResponse = await this.manager.connect(this.admin).setTargetAdminDelay(this.other, newDelay);
|
|
995
|
+
const setTargetAdminDelayAt = await time.clockFromReceipt.timestamp(txResponse);
|
|
996
|
+
await expect(txResponse)
|
|
997
|
+
.to.emit(this.manager, 'TargetAdminDelayUpdated')
|
|
998
|
+
.withArgs(this.other, newDelay, setTargetAdminDelayAt + MINSETBACK);
|
|
999
|
+
|
|
1000
|
+
expect(await this.manager.getTargetAdminDelay(this.other)).to.equal(oldDelay);
|
|
1001
|
+
await time.increaseBy.timestamp(MINSETBACK);
|
|
1002
|
+
expect(await this.manager.getTargetAdminDelay(this.other)).to.equal(newDelay);
|
|
1003
|
+
});
|
|
1004
|
+
});
|
|
1005
|
+
|
|
1006
|
+
describe('when reducing the delay', function () {
|
|
1007
|
+
const oldDelay = time.duration.days(10);
|
|
1008
|
+
|
|
1009
|
+
beforeEach('sets old delay', async function () {
|
|
1010
|
+
await this.manager.$_setTargetAdminDelay(this.other, oldDelay);
|
|
1011
|
+
await time.increaseBy.timestamp(MINSETBACK);
|
|
1012
|
+
expect(await this.manager.getTargetAdminDelay(this.other)).to.equal(oldDelay);
|
|
1013
|
+
});
|
|
1014
|
+
|
|
1015
|
+
describe('when the delay difference is shorter than minimum setback', function () {
|
|
1016
|
+
const newDelay = oldDelay - 1n;
|
|
1017
|
+
|
|
1018
|
+
it('increases the delay after minsetback', async function () {
|
|
1019
|
+
const txResponse = await this.manager.connect(this.admin).setTargetAdminDelay(this.other, newDelay);
|
|
1020
|
+
const setTargetAdminDelayAt = await time.clockFromReceipt.timestamp(txResponse);
|
|
1021
|
+
await expect(txResponse)
|
|
1022
|
+
.to.emit(this.manager, 'TargetAdminDelayUpdated')
|
|
1023
|
+
.withArgs(this.other, newDelay, setTargetAdminDelayAt + MINSETBACK);
|
|
1024
|
+
|
|
1025
|
+
expect(await this.manager.getTargetAdminDelay(this.other)).to.equal(oldDelay);
|
|
1026
|
+
await time.increaseBy.timestamp(MINSETBACK);
|
|
1027
|
+
expect(await this.manager.getTargetAdminDelay(this.other)).to.equal(newDelay);
|
|
1028
|
+
});
|
|
1029
|
+
});
|
|
1030
|
+
|
|
1031
|
+
describe('when the delay difference is longer than minimum setback', function () {
|
|
1032
|
+
const newDelay = 1n;
|
|
1033
|
+
|
|
1034
|
+
beforeEach('assert delay difference is higher than minsetback', function () {
|
|
1035
|
+
expect(oldDelay - newDelay).to.gt(MINSETBACK);
|
|
1036
|
+
});
|
|
1037
|
+
|
|
1038
|
+
it('increases the delay after delay difference', async function () {
|
|
1039
|
+
const setback = oldDelay - newDelay;
|
|
1040
|
+
|
|
1041
|
+
const txResponse = await this.manager.connect(this.admin).setTargetAdminDelay(this.other, newDelay);
|
|
1042
|
+
const setTargetAdminDelayAt = await time.clockFromReceipt.timestamp(txResponse);
|
|
1043
|
+
|
|
1044
|
+
await expect(txResponse)
|
|
1045
|
+
.to.emit(this.manager, 'TargetAdminDelayUpdated')
|
|
1046
|
+
.withArgs(this.other, newDelay, setTargetAdminDelayAt + setback);
|
|
1047
|
+
|
|
1048
|
+
expect(await this.manager.getTargetAdminDelay(this.other)).to.equal(oldDelay);
|
|
1049
|
+
await time.increaseBy.timestamp(setback);
|
|
1050
|
+
expect(await this.manager.getTargetAdminDelay(this.other)).to.equal(newDelay);
|
|
1051
|
+
});
|
|
1052
|
+
});
|
|
1053
|
+
});
|
|
1054
|
+
});
|
|
1055
|
+
});
|
|
1056
|
+
|
|
1057
|
+
describe('not subject to a delay', function () {
|
|
1058
|
+
describe('#updateAuthority', function () {
|
|
1059
|
+
beforeEach('create a target and a new authority', async function () {
|
|
1060
|
+
this.newAuthority = await ethers.deployContract('$AccessManager', [this.admin]);
|
|
1061
|
+
this.newManagedTarget = await ethers.deployContract('$AccessManagedTarget', [this.manager]);
|
|
1062
|
+
});
|
|
1063
|
+
|
|
1064
|
+
describe('restrictions', function () {
|
|
1065
|
+
beforeEach('set method and args', function () {
|
|
1066
|
+
this.calldata = this.manager.interface.encodeFunctionData('updateAuthority(address,address)', [
|
|
1067
|
+
this.newManagedTarget.target,
|
|
1068
|
+
this.newAuthority.target,
|
|
1069
|
+
]);
|
|
1070
|
+
});
|
|
1071
|
+
|
|
1072
|
+
shouldBehaveLikeNotDelayedAdminOperation();
|
|
1073
|
+
});
|
|
1074
|
+
|
|
1075
|
+
it('changes the authority', async function () {
|
|
1076
|
+
expect(await this.newManagedTarget.authority()).to.equal(this.manager);
|
|
1077
|
+
|
|
1078
|
+
await expect(this.manager.connect(this.admin).updateAuthority(this.newManagedTarget, this.newAuthority))
|
|
1079
|
+
.to.emit(this.newManagedTarget, 'AuthorityUpdated') // Managed contract is responsible of notifying the change through an event
|
|
1080
|
+
.withArgs(this.newAuthority);
|
|
1081
|
+
|
|
1082
|
+
expect(await this.newManagedTarget.authority()).to.equal(this.newAuthority);
|
|
1083
|
+
});
|
|
1084
|
+
});
|
|
1085
|
+
|
|
1086
|
+
describe('#setTargetClosed', function () {
|
|
1087
|
+
describe('restrictions', function () {
|
|
1088
|
+
beforeEach('set method and args', function () {
|
|
1089
|
+
const args = [this.other.address, true];
|
|
1090
|
+
const method = this.manager.interface.getFunction('setTargetClosed(address,bool)');
|
|
1091
|
+
this.calldata = this.manager.interface.encodeFunctionData(method, args);
|
|
1092
|
+
});
|
|
1093
|
+
|
|
1094
|
+
shouldBehaveLikeNotDelayedAdminOperation();
|
|
1095
|
+
});
|
|
1096
|
+
|
|
1097
|
+
it('closes and opens a target', async function () {
|
|
1098
|
+
await expect(this.manager.connect(this.admin).setTargetClosed(this.target, true))
|
|
1099
|
+
.to.emit(this.manager, 'TargetClosed')
|
|
1100
|
+
.withArgs(this.target, true);
|
|
1101
|
+
expect(await this.manager.isTargetClosed(this.target)).to.be.true;
|
|
1102
|
+
|
|
1103
|
+
await expect(this.manager.connect(this.admin).setTargetClosed(this.target, false))
|
|
1104
|
+
.to.emit(this.manager, 'TargetClosed')
|
|
1105
|
+
.withArgs(this.target, false);
|
|
1106
|
+
expect(await this.manager.isTargetClosed(this.target)).to.be.false;
|
|
1107
|
+
});
|
|
1108
|
+
|
|
1109
|
+
describe('when the target is the manager', async function () {
|
|
1110
|
+
it('closes and opens the manager', async function () {
|
|
1111
|
+
await expect(this.manager.connect(this.admin).setTargetClosed(this.manager, true))
|
|
1112
|
+
.to.emit(this.manager, 'TargetClosed')
|
|
1113
|
+
.withArgs(this.manager, true);
|
|
1114
|
+
expect(await this.manager.isTargetClosed(this.manager)).to.be.true;
|
|
1115
|
+
|
|
1116
|
+
await expect(this.manager.connect(this.admin).setTargetClosed(this.manager, false))
|
|
1117
|
+
.to.emit(this.manager, 'TargetClosed')
|
|
1118
|
+
.withArgs(this.manager, false);
|
|
1119
|
+
expect(await this.manager.isTargetClosed(this.manager)).to.be.false;
|
|
1120
|
+
});
|
|
1121
|
+
});
|
|
1122
|
+
});
|
|
1123
|
+
|
|
1124
|
+
describe('#setTargetFunctionRole', function () {
|
|
1125
|
+
describe('restrictions', function () {
|
|
1126
|
+
beforeEach('set method and args', function () {
|
|
1127
|
+
const args = [this.other.address, ['0x12345678'], 443342];
|
|
1128
|
+
const method = this.manager.interface.getFunction('setTargetFunctionRole(address,bytes4[],uint64)');
|
|
1129
|
+
this.calldata = this.manager.interface.encodeFunctionData(method, args);
|
|
1130
|
+
});
|
|
1131
|
+
|
|
1132
|
+
shouldBehaveLikeNotDelayedAdminOperation();
|
|
1133
|
+
});
|
|
1134
|
+
|
|
1135
|
+
const sigs = ['someFunction()', 'someOtherFunction(uint256)', 'oneMoreFunction(address,uint8)'].map(selector);
|
|
1136
|
+
|
|
1137
|
+
it('sets function roles', async function () {
|
|
1138
|
+
for (const sig of sigs) {
|
|
1139
|
+
expect(await this.manager.getTargetFunctionRole(this.target, sig)).to.equal(this.roles.ADMIN.id);
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
const allowRole = await this.manager
|
|
1143
|
+
.connect(this.admin)
|
|
1144
|
+
.setTargetFunctionRole(this.target, sigs, this.roles.SOME.id);
|
|
1145
|
+
|
|
1146
|
+
for (const sig of sigs) {
|
|
1147
|
+
await expect(allowRole)
|
|
1148
|
+
.to.emit(this.manager, 'TargetFunctionRoleUpdated')
|
|
1149
|
+
.withArgs(this.target, sig, this.roles.SOME.id);
|
|
1150
|
+
expect(await this.manager.getTargetFunctionRole(this.target, sig)).to.equal(this.roles.SOME.id);
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
await expect(
|
|
1154
|
+
this.manager.connect(this.admin).setTargetFunctionRole(this.target, [sigs[1]], this.roles.SOME_ADMIN.id),
|
|
1155
|
+
)
|
|
1156
|
+
.to.emit(this.manager, 'TargetFunctionRoleUpdated')
|
|
1157
|
+
.withArgs(this.target, sigs[1], this.roles.SOME_ADMIN.id);
|
|
1158
|
+
|
|
1159
|
+
for (const sig of sigs) {
|
|
1160
|
+
expect(await this.manager.getTargetFunctionRole(this.target, sig)).to.equal(
|
|
1161
|
+
sig == sigs[1] ? this.roles.SOME_ADMIN.id : this.roles.SOME.id,
|
|
1162
|
+
);
|
|
1163
|
+
}
|
|
1164
|
+
});
|
|
1165
|
+
});
|
|
1166
|
+
|
|
1167
|
+
describe('role admin operations', function () {
|
|
1168
|
+
const ANOTHER_ADMIN = 0xdeadc0de1n;
|
|
1169
|
+
const ANOTHER_ROLE = 0xdeadc0de2n;
|
|
1170
|
+
|
|
1171
|
+
beforeEach('set required role', async function () {
|
|
1172
|
+
// Make admin a member of ANOTHER_ADMIN
|
|
1173
|
+
await this.manager.$_grantRole(ANOTHER_ADMIN, this.admin, 0, 0);
|
|
1174
|
+
await this.manager.$_setRoleAdmin(ANOTHER_ROLE, ANOTHER_ADMIN);
|
|
1175
|
+
|
|
1176
|
+
this.role = { id: ANOTHER_ADMIN };
|
|
1177
|
+
await this.manager.$_grantRole(this.role.id, this.user, 0, 0);
|
|
1178
|
+
});
|
|
1179
|
+
|
|
1180
|
+
describe('#grantRole', function () {
|
|
1181
|
+
describe('restrictions', function () {
|
|
1182
|
+
beforeEach('set method and args', function () {
|
|
1183
|
+
const args = [ANOTHER_ROLE, this.other.address, 0];
|
|
1184
|
+
const method = this.manager.interface.getFunction('grantRole(uint64,address,uint32)');
|
|
1185
|
+
this.calldata = this.manager.interface.encodeFunctionData(method, args);
|
|
1186
|
+
});
|
|
1187
|
+
|
|
1188
|
+
shouldBehaveLikeRoleAdminOperation(ANOTHER_ADMIN);
|
|
1189
|
+
});
|
|
1190
|
+
|
|
1191
|
+
it('reverts when granting PUBLIC_ROLE', async function () {
|
|
1192
|
+
await expect(this.manager.connect(this.admin).grantRole(this.roles.PUBLIC.id, this.user, 0))
|
|
1193
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
|
|
1194
|
+
.withArgs(this.roles.PUBLIC.id);
|
|
1195
|
+
});
|
|
1196
|
+
|
|
1197
|
+
describe('when the user is not a role member', function () {
|
|
1198
|
+
describe('with grant delay', function () {
|
|
1199
|
+
beforeEach('set grant delay and grant role', async function () {
|
|
1200
|
+
// Delay granting
|
|
1201
|
+
this.grantDelay = time.duration.weeks(2);
|
|
1202
|
+
await this.manager.$_setGrantDelay(ANOTHER_ROLE, this.grantDelay);
|
|
1203
|
+
await time.increaseBy.timestamp(MINSETBACK);
|
|
1204
|
+
|
|
1205
|
+
// Grant role
|
|
1206
|
+
this.executionDelay = time.duration.days(3);
|
|
1207
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1208
|
+
false,
|
|
1209
|
+
'0',
|
|
1210
|
+
]);
|
|
1211
|
+
|
|
1212
|
+
this.txResponse = await this.manager
|
|
1213
|
+
.connect(this.admin)
|
|
1214
|
+
.grantRole(ANOTHER_ROLE, this.user, this.executionDelay);
|
|
1215
|
+
this.delay = this.grantDelay; // For testAsDelay
|
|
1216
|
+
});
|
|
1217
|
+
|
|
1218
|
+
testAsDelay('grant', {
|
|
1219
|
+
before: function self() {
|
|
1220
|
+
self.mineDelay = true;
|
|
1221
|
+
|
|
1222
|
+
it('does not grant role to the user yet', async function () {
|
|
1223
|
+
const timestamp = await time.clockFromReceipt.timestamp(this.txResponse);
|
|
1224
|
+
await expect(this.txResponse)
|
|
1225
|
+
.to.emit(this.manager, 'RoleGranted')
|
|
1226
|
+
.withArgs(ANOTHER_ROLE, this.user, this.executionDelay, timestamp + this.grantDelay, true);
|
|
1227
|
+
|
|
1228
|
+
// Access is correctly stored
|
|
1229
|
+
const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
|
|
1230
|
+
expect(access[0]).to.equal(timestamp + this.grantDelay); // inEffectSince
|
|
1231
|
+
expect(access[1]).to.equal(this.executionDelay); // currentDelay
|
|
1232
|
+
expect(access[2]).to.equal(0n); // pendingDelay
|
|
1233
|
+
expect(access[3]).to.equal(0n); // pendingDelayEffect
|
|
1234
|
+
|
|
1235
|
+
// Not in effect yet
|
|
1236
|
+
const currentTimestamp = await time.clock.timestamp();
|
|
1237
|
+
expect(currentTimestamp).to.be.lt(access[0]);
|
|
1238
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1239
|
+
false,
|
|
1240
|
+
this.executionDelay.toString(),
|
|
1241
|
+
]);
|
|
1242
|
+
});
|
|
1243
|
+
},
|
|
1244
|
+
after: function self() {
|
|
1245
|
+
self.mineDelay = true;
|
|
1246
|
+
|
|
1247
|
+
it('grants role to the user', async function () {
|
|
1248
|
+
const timestamp = await time.clockFromReceipt.timestamp(this.txResponse);
|
|
1249
|
+
await expect(this.txResponse)
|
|
1250
|
+
.to.emit(this.manager, 'RoleGranted')
|
|
1251
|
+
.withArgs(ANOTHER_ROLE, this.user, this.executionDelay, timestamp + this.grantDelay, true);
|
|
1252
|
+
|
|
1253
|
+
// Access is correctly stored
|
|
1254
|
+
const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
|
|
1255
|
+
expect(access[0]).to.equal(timestamp + this.grantDelay); // inEffectSince
|
|
1256
|
+
expect(access[1]).to.equal(this.executionDelay); // currentDelay
|
|
1257
|
+
expect(access[2]).to.equal(0n); // pendingDelay
|
|
1258
|
+
expect(access[3]).to.equal(0n); // pendingDelayEffect
|
|
1259
|
+
|
|
1260
|
+
// Already in effect
|
|
1261
|
+
const currentTimestamp = await time.clock.timestamp();
|
|
1262
|
+
expect(currentTimestamp).to.equal(access[0]);
|
|
1263
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1264
|
+
true,
|
|
1265
|
+
this.executionDelay.toString(),
|
|
1266
|
+
]);
|
|
1267
|
+
});
|
|
1268
|
+
},
|
|
1269
|
+
});
|
|
1270
|
+
});
|
|
1271
|
+
|
|
1272
|
+
describe('without grant delay', function () {
|
|
1273
|
+
beforeEach('set granting delay', async function () {
|
|
1274
|
+
// Delay granting
|
|
1275
|
+
this.grantDelay = 0;
|
|
1276
|
+
await this.manager.$_setGrantDelay(ANOTHER_ROLE, this.grantDelay);
|
|
1277
|
+
await time.increaseBy.timestamp(MINSETBACK);
|
|
1278
|
+
});
|
|
1279
|
+
|
|
1280
|
+
it('immediately grants the role to the user', async function () {
|
|
1281
|
+
const executionDelay = time.duration.days(6);
|
|
1282
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1283
|
+
false,
|
|
1284
|
+
'0',
|
|
1285
|
+
]);
|
|
1286
|
+
const txResponse = await this.manager
|
|
1287
|
+
.connect(this.admin)
|
|
1288
|
+
.grantRole(ANOTHER_ROLE, this.user, executionDelay);
|
|
1289
|
+
const grantedAt = await time.clockFromReceipt.timestamp(txResponse);
|
|
1290
|
+
await expect(txResponse)
|
|
1291
|
+
.to.emit(this.manager, 'RoleGranted')
|
|
1292
|
+
.withArgs(ANOTHER_ROLE, this.user, executionDelay, grantedAt, true);
|
|
1293
|
+
|
|
1294
|
+
// Access is correctly stored
|
|
1295
|
+
const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
|
|
1296
|
+
expect(access[0]).to.equal(grantedAt); // inEffectSince
|
|
1297
|
+
expect(access[1]).to.equal(executionDelay); // currentDelay
|
|
1298
|
+
expect(access[2]).to.equal(0n); // pendingDelay
|
|
1299
|
+
expect(access[3]).to.equal(0n); // pendingDelayEffect
|
|
1300
|
+
|
|
1301
|
+
// Already in effect
|
|
1302
|
+
const currentTimestamp = await time.clock.timestamp();
|
|
1303
|
+
expect(currentTimestamp).to.equal(access[0]);
|
|
1304
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1305
|
+
true,
|
|
1306
|
+
executionDelay.toString(),
|
|
1307
|
+
]);
|
|
1308
|
+
});
|
|
1309
|
+
});
|
|
1310
|
+
});
|
|
1311
|
+
|
|
1312
|
+
describe('when the user is already a role member', function () {
|
|
1313
|
+
beforeEach('make user role member', async function () {
|
|
1314
|
+
this.previousExecutionDelay = time.duration.days(6);
|
|
1315
|
+
await this.manager.$_grantRole(ANOTHER_ROLE, this.user, 0, this.previousExecutionDelay);
|
|
1316
|
+
this.oldAccess = await this.manager.getAccess(ANOTHER_ROLE, this.user);
|
|
1317
|
+
});
|
|
1318
|
+
|
|
1319
|
+
describe('with grant delay', function () {
|
|
1320
|
+
beforeEach('set granting delay', async function () {
|
|
1321
|
+
// Delay granting
|
|
1322
|
+
const grantDelay = time.duration.weeks(2);
|
|
1323
|
+
await this.manager.$_setGrantDelay(ANOTHER_ROLE, grantDelay);
|
|
1324
|
+
await time.increaseBy.timestamp(MINSETBACK);
|
|
1325
|
+
});
|
|
1326
|
+
|
|
1327
|
+
describe('when increasing the execution delay', function () {
|
|
1328
|
+
beforeEach('set increased new execution delay', async function () {
|
|
1329
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1330
|
+
true,
|
|
1331
|
+
this.previousExecutionDelay.toString(),
|
|
1332
|
+
]);
|
|
1333
|
+
|
|
1334
|
+
this.newExecutionDelay = this.previousExecutionDelay + time.duration.days(4);
|
|
1335
|
+
});
|
|
1336
|
+
|
|
1337
|
+
it('emits event and immediately changes the execution delay', async function () {
|
|
1338
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1339
|
+
true,
|
|
1340
|
+
this.previousExecutionDelay.toString(),
|
|
1341
|
+
]);
|
|
1342
|
+
const txResponse = await this.manager
|
|
1343
|
+
.connect(this.admin)
|
|
1344
|
+
.grantRole(ANOTHER_ROLE, this.user, this.newExecutionDelay);
|
|
1345
|
+
const timestamp = await time.clockFromReceipt.timestamp(txResponse);
|
|
1346
|
+
|
|
1347
|
+
await expect(txResponse)
|
|
1348
|
+
.to.emit(this.manager, 'RoleGranted')
|
|
1349
|
+
.withArgs(ANOTHER_ROLE, this.user, this.newExecutionDelay, timestamp, false);
|
|
1350
|
+
|
|
1351
|
+
// Access is correctly stored
|
|
1352
|
+
const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
|
|
1353
|
+
expect(access[0]).to.equal(this.oldAccess[0]); // inEffectSince
|
|
1354
|
+
expect(access[1]).to.equal(this.newExecutionDelay); // currentDelay
|
|
1355
|
+
expect(access[2]).to.equal(0n); // pendingDelay
|
|
1356
|
+
expect(access[3]).to.equal(0n); // pendingDelayEffect
|
|
1357
|
+
|
|
1358
|
+
// Already in effect
|
|
1359
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1360
|
+
true,
|
|
1361
|
+
this.newExecutionDelay.toString(),
|
|
1362
|
+
]);
|
|
1363
|
+
});
|
|
1364
|
+
});
|
|
1365
|
+
|
|
1366
|
+
describe('when decreasing the execution delay', function () {
|
|
1367
|
+
beforeEach('decrease execution delay', async function () {
|
|
1368
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1369
|
+
true,
|
|
1370
|
+
this.previousExecutionDelay.toString(),
|
|
1371
|
+
]);
|
|
1372
|
+
|
|
1373
|
+
this.newExecutionDelay = this.previousExecutionDelay - time.duration.days(4);
|
|
1374
|
+
this.txResponse = await this.manager
|
|
1375
|
+
.connect(this.admin)
|
|
1376
|
+
.grantRole(ANOTHER_ROLE, this.user, this.newExecutionDelay);
|
|
1377
|
+
this.grantTimestamp = await time.clockFromReceipt.timestamp(this.txResponse);
|
|
1378
|
+
|
|
1379
|
+
this.delay = this.previousExecutionDelay - this.newExecutionDelay; // For testAsDelay
|
|
1380
|
+
});
|
|
1381
|
+
|
|
1382
|
+
it('emits event', async function () {
|
|
1383
|
+
await expect(this.txResponse)
|
|
1384
|
+
.to.emit(this.manager, 'RoleGranted')
|
|
1385
|
+
.withArgs(ANOTHER_ROLE, this.user, this.newExecutionDelay, this.grantTimestamp + this.delay, false);
|
|
1386
|
+
});
|
|
1387
|
+
|
|
1388
|
+
testAsDelay('execution delay effect', {
|
|
1389
|
+
before: function self() {
|
|
1390
|
+
self.mineDelay = true;
|
|
1391
|
+
|
|
1392
|
+
it('does not change the execution delay yet', async function () {
|
|
1393
|
+
// Access is correctly stored
|
|
1394
|
+
const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
|
|
1395
|
+
expect(access[0]).to.equal(this.oldAccess[0]); // inEffectSince
|
|
1396
|
+
expect(access[1]).to.equal(this.previousExecutionDelay); // currentDelay
|
|
1397
|
+
expect(access[2]).to.equal(this.newExecutionDelay); // pendingDelay
|
|
1398
|
+
expect(access[3]).to.equal(this.grantTimestamp + this.delay); // pendingDelayEffect
|
|
1399
|
+
|
|
1400
|
+
// Not in effect yet
|
|
1401
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1402
|
+
true,
|
|
1403
|
+
this.previousExecutionDelay.toString(),
|
|
1404
|
+
]);
|
|
1405
|
+
});
|
|
1406
|
+
},
|
|
1407
|
+
after: function self() {
|
|
1408
|
+
self.mineDelay = true;
|
|
1409
|
+
|
|
1410
|
+
it('changes the execution delay', async function () {
|
|
1411
|
+
// Access is correctly stored
|
|
1412
|
+
const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
|
|
1413
|
+
|
|
1414
|
+
expect(access[0]).to.equal(this.oldAccess[0]); // inEffectSince
|
|
1415
|
+
expect(access[1]).to.equal(this.newExecutionDelay); // currentDelay
|
|
1416
|
+
expect(access[2]).to.equal(0n); // pendingDelay
|
|
1417
|
+
expect(access[3]).to.equal(0n); // pendingDelayEffect
|
|
1418
|
+
|
|
1419
|
+
// Already in effect
|
|
1420
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1421
|
+
true,
|
|
1422
|
+
this.newExecutionDelay.toString(),
|
|
1423
|
+
]);
|
|
1424
|
+
});
|
|
1425
|
+
},
|
|
1426
|
+
});
|
|
1427
|
+
});
|
|
1428
|
+
});
|
|
1429
|
+
|
|
1430
|
+
describe('without grant delay', function () {
|
|
1431
|
+
beforeEach('set granting delay', async function () {
|
|
1432
|
+
// Delay granting
|
|
1433
|
+
const grantDelay = 0;
|
|
1434
|
+
await this.manager.$_setGrantDelay(ANOTHER_ROLE, grantDelay);
|
|
1435
|
+
await time.increaseBy.timestamp(MINSETBACK);
|
|
1436
|
+
});
|
|
1437
|
+
|
|
1438
|
+
describe('when increasing the execution delay', function () {
|
|
1439
|
+
beforeEach('set increased new execution delay', async function () {
|
|
1440
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1441
|
+
true,
|
|
1442
|
+
this.previousExecutionDelay.toString(),
|
|
1443
|
+
]);
|
|
1444
|
+
|
|
1445
|
+
this.newExecutionDelay = this.previousExecutionDelay + time.duration.days(4);
|
|
1446
|
+
});
|
|
1447
|
+
|
|
1448
|
+
it('emits event and immediately changes the execution delay', async function () {
|
|
1449
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1450
|
+
true,
|
|
1451
|
+
this.previousExecutionDelay.toString(),
|
|
1452
|
+
]);
|
|
1453
|
+
const txResponse = await this.manager
|
|
1454
|
+
.connect(this.admin)
|
|
1455
|
+
.grantRole(ANOTHER_ROLE, this.user, this.newExecutionDelay);
|
|
1456
|
+
const timestamp = await time.clockFromReceipt.timestamp(txResponse);
|
|
1457
|
+
|
|
1458
|
+
await expect(txResponse)
|
|
1459
|
+
.to.emit(this.manager, 'RoleGranted')
|
|
1460
|
+
.withArgs(ANOTHER_ROLE, this.user, this.newExecutionDelay, timestamp, false);
|
|
1461
|
+
|
|
1462
|
+
// Access is correctly stored
|
|
1463
|
+
const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
|
|
1464
|
+
expect(access[0]).to.equal(this.oldAccess[0]); // inEffectSince
|
|
1465
|
+
expect(access[1]).to.equal(this.newExecutionDelay); // currentDelay
|
|
1466
|
+
expect(access[2]).to.equal(0n); // pendingDelay
|
|
1467
|
+
expect(access[3]).to.equal(0n); // pendingDelayEffect
|
|
1468
|
+
|
|
1469
|
+
// Already in effect
|
|
1470
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1471
|
+
true,
|
|
1472
|
+
this.newExecutionDelay.toString(),
|
|
1473
|
+
]);
|
|
1474
|
+
});
|
|
1475
|
+
});
|
|
1476
|
+
|
|
1477
|
+
describe('when decreasing the execution delay', function () {
|
|
1478
|
+
beforeEach('decrease execution delay', async function () {
|
|
1479
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1480
|
+
true,
|
|
1481
|
+
this.previousExecutionDelay.toString(),
|
|
1482
|
+
]);
|
|
1483
|
+
|
|
1484
|
+
this.newExecutionDelay = this.previousExecutionDelay - time.duration.days(4);
|
|
1485
|
+
this.txResponse = await this.manager
|
|
1486
|
+
.connect(this.admin)
|
|
1487
|
+
.grantRole(ANOTHER_ROLE, this.user, this.newExecutionDelay);
|
|
1488
|
+
this.grantTimestamp = await time.clockFromReceipt.timestamp(this.txResponse);
|
|
1489
|
+
|
|
1490
|
+
this.delay = this.previousExecutionDelay - this.newExecutionDelay; // For testAsDelay
|
|
1491
|
+
});
|
|
1492
|
+
|
|
1493
|
+
it('emits event', async function () {
|
|
1494
|
+
await expect(this.txResponse)
|
|
1495
|
+
.to.emit(this.manager, 'RoleGranted')
|
|
1496
|
+
.withArgs(ANOTHER_ROLE, this.user, this.newExecutionDelay, this.grantTimestamp + this.delay, false);
|
|
1497
|
+
});
|
|
1498
|
+
|
|
1499
|
+
testAsDelay('execution delay effect', {
|
|
1500
|
+
before: function self() {
|
|
1501
|
+
self.mineDelay = true;
|
|
1502
|
+
|
|
1503
|
+
it('does not change the execution delay yet', async function () {
|
|
1504
|
+
// Access is correctly stored
|
|
1505
|
+
const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
|
|
1506
|
+
expect(access[0]).to.equal(this.oldAccess[0]); // inEffectSince
|
|
1507
|
+
expect(access[1]).to.equal(this.previousExecutionDelay); // currentDelay
|
|
1508
|
+
expect(access[2]).to.equal(this.newExecutionDelay); // pendingDelay
|
|
1509
|
+
expect(access[3]).to.equal(this.grantTimestamp + this.delay); // pendingDelayEffect
|
|
1510
|
+
|
|
1511
|
+
// Not in effect yet
|
|
1512
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1513
|
+
true,
|
|
1514
|
+
this.previousExecutionDelay.toString(),
|
|
1515
|
+
]);
|
|
1516
|
+
});
|
|
1517
|
+
},
|
|
1518
|
+
after: function self() {
|
|
1519
|
+
self.mineDelay = true;
|
|
1520
|
+
|
|
1521
|
+
it('changes the execution delay', async function () {
|
|
1522
|
+
// Access is correctly stored
|
|
1523
|
+
const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
|
|
1524
|
+
|
|
1525
|
+
expect(access[0]).to.equal(this.oldAccess[0]); // inEffectSince
|
|
1526
|
+
expect(access[1]).to.equal(this.newExecutionDelay); // currentDelay
|
|
1527
|
+
expect(access[2]).to.equal(0n); // pendingDelay
|
|
1528
|
+
expect(access[3]).to.equal(0n); // pendingDelayEffect
|
|
1529
|
+
|
|
1530
|
+
// Already in effect
|
|
1531
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1532
|
+
true,
|
|
1533
|
+
this.newExecutionDelay.toString(),
|
|
1534
|
+
]);
|
|
1535
|
+
});
|
|
1536
|
+
},
|
|
1537
|
+
});
|
|
1538
|
+
});
|
|
1539
|
+
});
|
|
1540
|
+
});
|
|
1541
|
+
});
|
|
1542
|
+
|
|
1543
|
+
describe('#revokeRole', function () {
|
|
1544
|
+
describe('restrictions', function () {
|
|
1545
|
+
beforeEach('set method and args', async function () {
|
|
1546
|
+
const args = [ANOTHER_ROLE, this.other.address];
|
|
1547
|
+
const method = this.manager.interface.getFunction('revokeRole(uint64,address)');
|
|
1548
|
+
this.calldata = this.manager.interface.encodeFunctionData(method, args);
|
|
1549
|
+
|
|
1550
|
+
// Need to be set before revoking
|
|
1551
|
+
await this.manager.$_grantRole(...args, 0, 0);
|
|
1552
|
+
});
|
|
1553
|
+
|
|
1554
|
+
shouldBehaveLikeRoleAdminOperation(ANOTHER_ADMIN);
|
|
1555
|
+
});
|
|
1556
|
+
|
|
1557
|
+
describe('when role has been granted', function () {
|
|
1558
|
+
beforeEach('grant role with grant delay', async function () {
|
|
1559
|
+
this.grantDelay = time.duration.weeks(1);
|
|
1560
|
+
await this.manager.$_grantRole(ANOTHER_ROLE, this.user, this.grantDelay, 0);
|
|
1561
|
+
|
|
1562
|
+
this.delay = this.grantDelay; // For testAsDelay
|
|
1563
|
+
});
|
|
1564
|
+
|
|
1565
|
+
testAsDelay('grant', {
|
|
1566
|
+
before: function self() {
|
|
1567
|
+
self.mineDelay = true;
|
|
1568
|
+
|
|
1569
|
+
it('revokes a granted role that will take effect in the future', async function () {
|
|
1570
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1571
|
+
false,
|
|
1572
|
+
'0',
|
|
1573
|
+
]);
|
|
1574
|
+
|
|
1575
|
+
await expect(this.manager.connect(this.admin).revokeRole(ANOTHER_ROLE, this.user))
|
|
1576
|
+
.to.emit(this.manager, 'RoleRevoked')
|
|
1577
|
+
.withArgs(ANOTHER_ROLE, this.user);
|
|
1578
|
+
|
|
1579
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1580
|
+
false,
|
|
1581
|
+
'0',
|
|
1582
|
+
]);
|
|
1583
|
+
|
|
1584
|
+
const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
|
|
1585
|
+
expect(access[0]).to.equal(0n); // inRoleSince
|
|
1586
|
+
expect(access[1]).to.equal(0n); // currentDelay
|
|
1587
|
+
expect(access[2]).to.equal(0n); // pendingDelay
|
|
1588
|
+
expect(access[3]).to.equal(0n); // effect
|
|
1589
|
+
});
|
|
1590
|
+
},
|
|
1591
|
+
after: function self() {
|
|
1592
|
+
self.mineDelay = true;
|
|
1593
|
+
|
|
1594
|
+
it('revokes a granted role that already took effect', async function () {
|
|
1595
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1596
|
+
true,
|
|
1597
|
+
'0',
|
|
1598
|
+
]);
|
|
1599
|
+
|
|
1600
|
+
await expect(this.manager.connect(this.admin).revokeRole(ANOTHER_ROLE, this.user))
|
|
1601
|
+
.to.emit(this.manager, 'RoleRevoked')
|
|
1602
|
+
.withArgs(ANOTHER_ROLE, this.user);
|
|
1603
|
+
|
|
1604
|
+
expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1605
|
+
false,
|
|
1606
|
+
'0',
|
|
1607
|
+
]);
|
|
1608
|
+
|
|
1609
|
+
const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
|
|
1610
|
+
expect(access[0]).to.equal(0n); // inRoleSince
|
|
1611
|
+
expect(access[1]).to.equal(0n); // currentDelay
|
|
1612
|
+
expect(access[2]).to.equal(0n); // pendingDelay
|
|
1613
|
+
expect(access[3]).to.equal(0n); // effect
|
|
1614
|
+
});
|
|
1615
|
+
},
|
|
1616
|
+
});
|
|
1617
|
+
});
|
|
1618
|
+
|
|
1619
|
+
describe('when role has not been granted', function () {
|
|
1620
|
+
it('has no effect', async function () {
|
|
1621
|
+
expect(await this.manager.hasRole(this.roles.SOME.id, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1622
|
+
false,
|
|
1623
|
+
'0',
|
|
1624
|
+
]);
|
|
1625
|
+
await expect(this.manager.connect(this.roleAdmin).revokeRole(this.roles.SOME.id, this.user)).to.not.emit(
|
|
1626
|
+
this.manager,
|
|
1627
|
+
'RoleRevoked',
|
|
1628
|
+
);
|
|
1629
|
+
expect(await this.manager.hasRole(this.roles.SOME.id, this.user).then(formatAccess)).to.be.deep.equal([
|
|
1630
|
+
false,
|
|
1631
|
+
'0',
|
|
1632
|
+
]);
|
|
1633
|
+
});
|
|
1634
|
+
});
|
|
1635
|
+
|
|
1636
|
+
it('reverts revoking PUBLIC_ROLE', async function () {
|
|
1637
|
+
await expect(this.manager.connect(this.admin).revokeRole(this.roles.PUBLIC.id, this.user))
|
|
1638
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
|
|
1639
|
+
.withArgs(this.roles.PUBLIC.id);
|
|
1640
|
+
});
|
|
1641
|
+
});
|
|
1642
|
+
});
|
|
1643
|
+
|
|
1644
|
+
describe('self role operations', function () {
|
|
1645
|
+
describe('#renounceRole', function () {
|
|
1646
|
+
beforeEach('grant role', async function () {
|
|
1647
|
+
this.role = { id: 783164n };
|
|
1648
|
+
this.caller = this.user;
|
|
1649
|
+
await this.manager.$_grantRole(this.role.id, this.caller, 0, 0);
|
|
1650
|
+
});
|
|
1651
|
+
|
|
1652
|
+
it('renounces a role', async function () {
|
|
1653
|
+
expect(await this.manager.hasRole(this.role.id, this.caller).then(formatAccess)).to.be.deep.equal([
|
|
1654
|
+
true,
|
|
1655
|
+
'0',
|
|
1656
|
+
]);
|
|
1657
|
+
await expect(this.manager.connect(this.caller).renounceRole(this.role.id, this.caller))
|
|
1658
|
+
.to.emit(this.manager, 'RoleRevoked')
|
|
1659
|
+
.withArgs(this.role.id, this.caller);
|
|
1660
|
+
expect(await this.manager.hasRole(this.role.id, this.caller).then(formatAccess)).to.be.deep.equal([
|
|
1661
|
+
false,
|
|
1662
|
+
'0',
|
|
1663
|
+
]);
|
|
1664
|
+
});
|
|
1665
|
+
|
|
1666
|
+
it('reverts if renouncing the PUBLIC_ROLE', async function () {
|
|
1667
|
+
await expect(this.manager.connect(this.caller).renounceRole(this.roles.PUBLIC.id, this.caller))
|
|
1668
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
|
|
1669
|
+
.withArgs(this.roles.PUBLIC.id);
|
|
1670
|
+
});
|
|
1671
|
+
|
|
1672
|
+
it('reverts if renouncing with bad caller confirmation', async function () {
|
|
1673
|
+
await expect(
|
|
1674
|
+
this.manager.connect(this.caller).renounceRole(this.role.id, this.other),
|
|
1675
|
+
).to.be.revertedWithCustomError(this.manager, 'AccessManagerBadConfirmation');
|
|
1676
|
+
});
|
|
1677
|
+
});
|
|
1678
|
+
});
|
|
1679
|
+
});
|
|
1680
|
+
});
|
|
1681
|
+
|
|
1682
|
+
describe('access managed self operations', function () {
|
|
1683
|
+
describe('when calling a restricted target function', function () {
|
|
1684
|
+
const method = 'fnRestricted()';
|
|
1685
|
+
|
|
1686
|
+
beforeEach('set required role', async function () {
|
|
1687
|
+
this.role = { id: 785913n };
|
|
1688
|
+
await this.manager.$_setTargetFunctionRole(
|
|
1689
|
+
this.manager,
|
|
1690
|
+
this.manager[method].getFragment().selector,
|
|
1691
|
+
this.role.id,
|
|
1692
|
+
);
|
|
1693
|
+
});
|
|
1694
|
+
|
|
1695
|
+
describe('restrictions', function () {
|
|
1696
|
+
beforeEach('set method and args', function () {
|
|
1697
|
+
this.caller = this.user;
|
|
1698
|
+
this.calldata = this.manager.interface.encodeFunctionData(method, []);
|
|
1699
|
+
});
|
|
1700
|
+
|
|
1701
|
+
shouldBehaveLikeASelfRestrictedOperation();
|
|
1702
|
+
});
|
|
1703
|
+
|
|
1704
|
+
it('succeeds called by a role member', async function () {
|
|
1705
|
+
await this.manager.$_grantRole(this.role.id, this.user, 0, 0);
|
|
1706
|
+
|
|
1707
|
+
await expect(this.manager.connect(this.user)[method]())
|
|
1708
|
+
.to.emit(this.manager, 'CalledRestricted')
|
|
1709
|
+
.withArgs(this.user);
|
|
1710
|
+
});
|
|
1711
|
+
});
|
|
1712
|
+
|
|
1713
|
+
describe('when calling a non-restricted target function', function () {
|
|
1714
|
+
const method = 'fnUnrestricted()';
|
|
1715
|
+
|
|
1716
|
+
beforeEach('set required role', async function () {
|
|
1717
|
+
this.role = { id: 879435n };
|
|
1718
|
+
await this.manager.$_setTargetFunctionRole(
|
|
1719
|
+
this.manager,
|
|
1720
|
+
this.manager[method].getFragment().selector,
|
|
1721
|
+
this.role.id,
|
|
1722
|
+
);
|
|
1723
|
+
});
|
|
1724
|
+
|
|
1725
|
+
it('succeeds called by anyone', async function () {
|
|
1726
|
+
await expect(this.manager.connect(this.user)[method]())
|
|
1727
|
+
.to.emit(this.manager, 'CalledUnrestricted')
|
|
1728
|
+
.withArgs(this.user);
|
|
1729
|
+
});
|
|
1730
|
+
});
|
|
1731
|
+
});
|
|
1732
|
+
|
|
1733
|
+
describe('access managed target operations', function () {
|
|
1734
|
+
describe('when calling a restricted target function', function () {
|
|
1735
|
+
const method = 'fnRestricted()';
|
|
1736
|
+
|
|
1737
|
+
beforeEach('set required role', async function () {
|
|
1738
|
+
this.role = { id: 3597243n };
|
|
1739
|
+
await this.manager.$_setTargetFunctionRole(
|
|
1740
|
+
this.target,
|
|
1741
|
+
this.target[method].getFragment().selector,
|
|
1742
|
+
this.role.id,
|
|
1743
|
+
);
|
|
1744
|
+
});
|
|
1745
|
+
|
|
1746
|
+
describe('restrictions', function () {
|
|
1747
|
+
beforeEach('set method and args', function () {
|
|
1748
|
+
this.caller = this.user;
|
|
1749
|
+
this.calldata = this.target.interface.encodeFunctionData(method, []);
|
|
1750
|
+
});
|
|
1751
|
+
|
|
1752
|
+
shouldBehaveLikeAManagedRestrictedOperation();
|
|
1753
|
+
});
|
|
1754
|
+
|
|
1755
|
+
it('succeeds called by a role member', async function () {
|
|
1756
|
+
await this.manager.$_grantRole(this.role.id, this.user, 0, 0);
|
|
1757
|
+
|
|
1758
|
+
await expect(this.target.connect(this.user)[method]())
|
|
1759
|
+
.to.emit(this.target, 'CalledRestricted')
|
|
1760
|
+
.withArgs(this.user);
|
|
1761
|
+
});
|
|
1762
|
+
});
|
|
1763
|
+
|
|
1764
|
+
describe('when calling a non-restricted target function', function () {
|
|
1765
|
+
const method = 'fnUnrestricted()';
|
|
1766
|
+
|
|
1767
|
+
beforeEach('set required role', async function () {
|
|
1768
|
+
this.role = { id: 879435n };
|
|
1769
|
+
await this.manager.$_setTargetFunctionRole(
|
|
1770
|
+
this.target,
|
|
1771
|
+
this.target[method].getFragment().selector,
|
|
1772
|
+
this.role.id,
|
|
1773
|
+
);
|
|
1774
|
+
});
|
|
1775
|
+
|
|
1776
|
+
it('succeeds called by anyone', async function () {
|
|
1777
|
+
await expect(this.target.connect(this.user)[method]())
|
|
1778
|
+
.to.emit(this.target, 'CalledUnrestricted')
|
|
1779
|
+
.withArgs(this.user);
|
|
1780
|
+
});
|
|
1781
|
+
});
|
|
1782
|
+
});
|
|
1783
|
+
|
|
1784
|
+
describe('#schedule', function () {
|
|
1785
|
+
beforeEach('set target function role', async function () {
|
|
1786
|
+
this.method = this.target.fnRestricted.getFragment();
|
|
1787
|
+
this.role = { id: 498305n };
|
|
1788
|
+
this.caller = this.user;
|
|
1789
|
+
|
|
1790
|
+
await this.manager.$_setTargetFunctionRole(this.target, this.method.selector, this.role.id);
|
|
1791
|
+
await this.manager.$_grantRole(this.role.id, this.caller, 0, 1); // nonzero execution delay
|
|
1792
|
+
|
|
1793
|
+
this.calldata = this.target.interface.encodeFunctionData(this.method, []);
|
|
1794
|
+
this.delay = time.duration.weeks(2);
|
|
1795
|
+
});
|
|
1796
|
+
|
|
1797
|
+
describe('restrictions', function () {
|
|
1798
|
+
testAsCanCall({
|
|
1799
|
+
closed() {
|
|
1800
|
+
it('reverts as AccessManagerUnauthorizedCall', async function () {
|
|
1801
|
+
const { schedule } = await prepareOperation(this.manager, {
|
|
1802
|
+
caller: this.caller,
|
|
1803
|
+
target: this.target,
|
|
1804
|
+
calldata: this.calldata,
|
|
1805
|
+
delay: this.delay,
|
|
1806
|
+
});
|
|
1807
|
+
await expect(schedule())
|
|
1808
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
|
|
1809
|
+
.withArgs(this.caller, this.target, this.calldata.substring(0, 10));
|
|
1810
|
+
});
|
|
1811
|
+
},
|
|
1812
|
+
open: {
|
|
1813
|
+
callerIsTheManager: {
|
|
1814
|
+
executing() {
|
|
1815
|
+
it.skip('is not reachable because schedule is not restrictable');
|
|
1816
|
+
},
|
|
1817
|
+
notExecuting() {
|
|
1818
|
+
it('reverts as AccessManagerUnauthorizedCall', async function () {
|
|
1819
|
+
const { schedule } = await prepareOperation(this.manager, {
|
|
1820
|
+
caller: this.caller,
|
|
1821
|
+
target: this.target,
|
|
1822
|
+
calldata: this.calldata,
|
|
1823
|
+
delay: this.delay,
|
|
1824
|
+
});
|
|
1825
|
+
await expect(schedule())
|
|
1826
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
|
|
1827
|
+
.withArgs(this.caller, this.target, this.calldata.substring(0, 10));
|
|
1828
|
+
});
|
|
1829
|
+
},
|
|
1830
|
+
},
|
|
1831
|
+
callerIsNotTheManager: {
|
|
1832
|
+
publicRoleIsRequired() {
|
|
1833
|
+
it('reverts as AccessManagerUnauthorizedCall', async function () {
|
|
1834
|
+
// prepareOperation is not used here because it alters the next block timestamp
|
|
1835
|
+
await expect(this.manager.connect(this.caller).schedule(this.target, this.calldata, MAX_UINT48))
|
|
1836
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
|
|
1837
|
+
.withArgs(this.caller, this.target, this.calldata.substring(0, 10));
|
|
1838
|
+
});
|
|
1839
|
+
},
|
|
1840
|
+
specificRoleIsRequired: {
|
|
1841
|
+
requiredRoleIsGranted: {
|
|
1842
|
+
roleGrantingIsDelayed: {
|
|
1843
|
+
callerHasAnExecutionDelay: {
|
|
1844
|
+
beforeGrantDelay() {
|
|
1845
|
+
it('reverts as AccessManagerUnauthorizedCall', async function () {
|
|
1846
|
+
// prepareOperation is not used here because it alters the next block timestamp
|
|
1847
|
+
await expect(this.manager.connect(this.caller).schedule(this.target, this.calldata, MAX_UINT48))
|
|
1848
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
|
|
1849
|
+
.withArgs(this.caller, this.target, this.calldata.substring(0, 10));
|
|
1850
|
+
});
|
|
1851
|
+
},
|
|
1852
|
+
afterGrantDelay() {
|
|
1853
|
+
it('succeeds', async function () {
|
|
1854
|
+
// prepareOperation is not used here because it alters the next block timestamp
|
|
1855
|
+
await this.manager.connect(this.caller).schedule(this.target, this.calldata, MAX_UINT48);
|
|
1856
|
+
});
|
|
1857
|
+
},
|
|
1858
|
+
},
|
|
1859
|
+
callerHasNoExecutionDelay: {
|
|
1860
|
+
beforeGrantDelay() {
|
|
1861
|
+
it('reverts as AccessManagerUnauthorizedCall', async function () {
|
|
1862
|
+
// prepareOperation is not used here because it alters the next block timestamp
|
|
1863
|
+
await expect(this.manager.connect(this.caller).schedule(this.target, this.calldata, MAX_UINT48))
|
|
1864
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
|
|
1865
|
+
.withArgs(this.caller, this.target, this.calldata.substring(0, 10));
|
|
1866
|
+
});
|
|
1867
|
+
},
|
|
1868
|
+
afterGrantDelay() {
|
|
1869
|
+
it('reverts as AccessManagerUnauthorizedCall', async function () {
|
|
1870
|
+
// prepareOperation is not used here because it alters the next block timestamp
|
|
1871
|
+
await expect(this.manager.connect(this.caller).schedule(this.target, this.calldata, MAX_UINT48))
|
|
1872
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
|
|
1873
|
+
.withArgs(this.caller, this.target, this.calldata.substring(0, 10));
|
|
1874
|
+
});
|
|
1875
|
+
},
|
|
1876
|
+
},
|
|
1877
|
+
},
|
|
1878
|
+
roleGrantingIsNotDelayed: {
|
|
1879
|
+
callerHasAnExecutionDelay() {
|
|
1880
|
+
it('succeeds', async function () {
|
|
1881
|
+
const { schedule } = await prepareOperation(this.manager, {
|
|
1882
|
+
caller: this.caller,
|
|
1883
|
+
target: this.target,
|
|
1884
|
+
calldata: this.calldata,
|
|
1885
|
+
delay: this.delay,
|
|
1886
|
+
});
|
|
1887
|
+
|
|
1888
|
+
await schedule();
|
|
1889
|
+
});
|
|
1890
|
+
},
|
|
1891
|
+
callerHasNoExecutionDelay() {
|
|
1892
|
+
it('reverts as AccessManagerUnauthorizedCall', async function () {
|
|
1893
|
+
// prepareOperation is not used here because it alters the next block timestamp
|
|
1894
|
+
await expect(this.manager.connect(this.caller).schedule(this.target, this.calldata, MAX_UINT48))
|
|
1895
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
|
|
1896
|
+
.withArgs(this.caller, this.target, this.calldata.substring(0, 10));
|
|
1897
|
+
});
|
|
1898
|
+
},
|
|
1899
|
+
},
|
|
1900
|
+
},
|
|
1901
|
+
requiredRoleIsNotGranted() {
|
|
1902
|
+
it('reverts as AccessManagerUnauthorizedCall', async function () {
|
|
1903
|
+
const { schedule } = await prepareOperation(this.manager, {
|
|
1904
|
+
caller: this.caller,
|
|
1905
|
+
target: this.target,
|
|
1906
|
+
calldata: this.calldata,
|
|
1907
|
+
delay: this.delay,
|
|
1908
|
+
});
|
|
1909
|
+
await expect(schedule())
|
|
1910
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
|
|
1911
|
+
.withArgs(this.caller, this.target, this.calldata.substring(0, 10));
|
|
1912
|
+
});
|
|
1913
|
+
},
|
|
1914
|
+
},
|
|
1915
|
+
},
|
|
1916
|
+
},
|
|
1917
|
+
});
|
|
1918
|
+
});
|
|
1919
|
+
|
|
1920
|
+
it('schedules an operation at the specified execution date if it is larger than caller execution delay', async function () {
|
|
1921
|
+
const { operationId, scheduledAt, schedule } = await prepareOperation(this.manager, {
|
|
1922
|
+
caller: this.caller,
|
|
1923
|
+
target: this.target,
|
|
1924
|
+
calldata: this.calldata,
|
|
1925
|
+
delay: this.delay,
|
|
1926
|
+
});
|
|
1927
|
+
|
|
1928
|
+
const txResponse = await schedule();
|
|
1929
|
+
|
|
1930
|
+
expect(await this.manager.getSchedule(operationId)).to.equal(scheduledAt + this.delay);
|
|
1931
|
+
await expect(txResponse)
|
|
1932
|
+
.to.emit(this.manager, 'OperationScheduled')
|
|
1933
|
+
.withArgs(operationId, '1', scheduledAt + this.delay, this.caller, this.target, this.calldata);
|
|
1934
|
+
});
|
|
1935
|
+
|
|
1936
|
+
it('schedules an operation at the minimum execution date if no specified execution date (when == 0)', async function () {
|
|
1937
|
+
const executionDelay = await time.duration.hours(72);
|
|
1938
|
+
await this.manager.$_grantRole(this.role.id, this.caller, 0, executionDelay);
|
|
1939
|
+
|
|
1940
|
+
const txResponse = await this.manager.connect(this.caller).schedule(this.target, this.calldata, 0);
|
|
1941
|
+
const scheduledAt = await time.clockFromReceipt.timestamp(txResponse);
|
|
1942
|
+
|
|
1943
|
+
const operationId = await this.manager.hashOperation(this.caller, this.target, this.calldata);
|
|
1944
|
+
|
|
1945
|
+
expect(await this.manager.getSchedule(operationId)).to.equal(scheduledAt + executionDelay);
|
|
1946
|
+
await expect(txResponse)
|
|
1947
|
+
.to.emit(this.manager, 'OperationScheduled')
|
|
1948
|
+
.withArgs(operationId, '1', scheduledAt + executionDelay, this.caller, this.target, this.calldata);
|
|
1949
|
+
});
|
|
1950
|
+
|
|
1951
|
+
it('increases the nonce of an operation scheduled more than once', async function () {
|
|
1952
|
+
// Setup and check initial nonce
|
|
1953
|
+
const expectedOperationId = hashOperation(this.caller, this.target, this.calldata);
|
|
1954
|
+
expect(await this.manager.getNonce(expectedOperationId)).to.equal('0');
|
|
1955
|
+
|
|
1956
|
+
// Schedule
|
|
1957
|
+
const op1 = await prepareOperation(this.manager, {
|
|
1958
|
+
caller: this.caller,
|
|
1959
|
+
target: this.target,
|
|
1960
|
+
calldata: this.calldata,
|
|
1961
|
+
delay: this.delay,
|
|
1962
|
+
});
|
|
1963
|
+
await expect(op1.schedule())
|
|
1964
|
+
.to.emit(this.manager, 'OperationScheduled')
|
|
1965
|
+
.withArgs(op1.operationId, 1n, op1.scheduledAt + this.delay, this.caller, this.target, this.calldata);
|
|
1966
|
+
expect(expectedOperationId).to.equal(op1.operationId);
|
|
1967
|
+
|
|
1968
|
+
// Consume
|
|
1969
|
+
await time.increaseBy.timestamp(this.delay);
|
|
1970
|
+
await this.manager.$_consumeScheduledOp(expectedOperationId);
|
|
1971
|
+
|
|
1972
|
+
// Check nonce
|
|
1973
|
+
expect(await this.manager.getNonce(expectedOperationId)).to.equal('1');
|
|
1974
|
+
|
|
1975
|
+
// Schedule again
|
|
1976
|
+
const op2 = await prepareOperation(this.manager, {
|
|
1977
|
+
caller: this.caller,
|
|
1978
|
+
target: this.target,
|
|
1979
|
+
calldata: this.calldata,
|
|
1980
|
+
delay: this.delay,
|
|
1981
|
+
});
|
|
1982
|
+
await expect(op2.schedule())
|
|
1983
|
+
.to.emit(this.manager, 'OperationScheduled')
|
|
1984
|
+
.withArgs(op2.operationId, 2n, op2.scheduledAt + this.delay, this.caller, this.target, this.calldata);
|
|
1985
|
+
expect(expectedOperationId).to.equal(op2.operationId);
|
|
1986
|
+
|
|
1987
|
+
// Check final nonce
|
|
1988
|
+
expect(await this.manager.getNonce(expectedOperationId)).to.equal('2');
|
|
1989
|
+
});
|
|
1990
|
+
|
|
1991
|
+
it('reverts if the specified execution date is before the current timestamp + caller execution delay', async function () {
|
|
1992
|
+
const executionDelay = time.duration.weeks(1) + this.delay;
|
|
1993
|
+
await this.manager.$_grantRole(this.role.id, this.caller, 0, executionDelay);
|
|
1994
|
+
|
|
1995
|
+
const { schedule } = await prepareOperation(this.manager, {
|
|
1996
|
+
caller: this.caller,
|
|
1997
|
+
target: this.target,
|
|
1998
|
+
calldata: this.calldata,
|
|
1999
|
+
delay: this.delay,
|
|
2000
|
+
});
|
|
2001
|
+
|
|
2002
|
+
await expect(schedule())
|
|
2003
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
|
|
2004
|
+
.withArgs(this.caller, this.target, this.calldata.substring(0, 10));
|
|
2005
|
+
});
|
|
2006
|
+
|
|
2007
|
+
it('reverts if an operation is already schedule', async function () {
|
|
2008
|
+
const op1 = await prepareOperation(this.manager, {
|
|
2009
|
+
caller: this.caller,
|
|
2010
|
+
target: this.target,
|
|
2011
|
+
calldata: this.calldata,
|
|
2012
|
+
delay: this.delay,
|
|
2013
|
+
});
|
|
2014
|
+
|
|
2015
|
+
await op1.schedule();
|
|
2016
|
+
|
|
2017
|
+
const op2 = await prepareOperation(this.manager, {
|
|
2018
|
+
caller: this.caller,
|
|
2019
|
+
target: this.target,
|
|
2020
|
+
calldata: this.calldata,
|
|
2021
|
+
delay: this.delay,
|
|
2022
|
+
});
|
|
2023
|
+
|
|
2024
|
+
await expect(op2.schedule())
|
|
2025
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerAlreadyScheduled')
|
|
2026
|
+
.withArgs(op1.operationId);
|
|
2027
|
+
});
|
|
2028
|
+
|
|
2029
|
+
it('panics scheduling calldata with less than 4 bytes', async function () {
|
|
2030
|
+
const calldata = '0x1234'; // 2 bytes
|
|
2031
|
+
|
|
2032
|
+
// Managed contract
|
|
2033
|
+
const op1 = await prepareOperation(this.manager, {
|
|
2034
|
+
caller: this.caller,
|
|
2035
|
+
target: this.target,
|
|
2036
|
+
calldata: calldata,
|
|
2037
|
+
delay: this.delay,
|
|
2038
|
+
});
|
|
2039
|
+
await expect(op1.schedule()).to.be.revertedWithoutReason();
|
|
2040
|
+
|
|
2041
|
+
// Manager contract
|
|
2042
|
+
const op2 = await prepareOperation(this.manager, {
|
|
2043
|
+
caller: this.caller,
|
|
2044
|
+
target: this.manager,
|
|
2045
|
+
calldata: calldata,
|
|
2046
|
+
delay: this.delay,
|
|
2047
|
+
});
|
|
2048
|
+
await expect(op2.schedule()).to.be.revertedWithoutReason();
|
|
2049
|
+
});
|
|
2050
|
+
|
|
2051
|
+
it('reverts scheduling an unknown operation to the manager', async function () {
|
|
2052
|
+
const calldata = '0x12345678';
|
|
2053
|
+
|
|
2054
|
+
const { schedule } = await prepareOperation(this.manager, {
|
|
2055
|
+
caller: this.caller,
|
|
2056
|
+
target: this.manager,
|
|
2057
|
+
calldata,
|
|
2058
|
+
delay: this.delay,
|
|
2059
|
+
});
|
|
2060
|
+
|
|
2061
|
+
await expect(schedule())
|
|
2062
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
|
|
2063
|
+
.withArgs(this.caller, this.manager, calldata);
|
|
2064
|
+
});
|
|
2065
|
+
});
|
|
2066
|
+
|
|
2067
|
+
describe('#execute', function () {
|
|
2068
|
+
beforeEach('set target function role', async function () {
|
|
2069
|
+
this.method = this.target.fnRestricted.getFragment();
|
|
2070
|
+
this.role = { id: 9825430n };
|
|
2071
|
+
this.caller = this.user;
|
|
2072
|
+
|
|
2073
|
+
await this.manager.$_setTargetFunctionRole(this.target, this.method.selector, this.role.id);
|
|
2074
|
+
await this.manager.$_grantRole(this.role.id, this.caller, 0, 0);
|
|
2075
|
+
|
|
2076
|
+
this.calldata = this.target.interface.encodeFunctionData(this.method, []);
|
|
2077
|
+
});
|
|
2078
|
+
|
|
2079
|
+
describe('restrictions', function () {
|
|
2080
|
+
testAsCanCall({
|
|
2081
|
+
closed() {
|
|
2082
|
+
it('reverts as AccessManagerUnauthorizedCall', async function () {
|
|
2083
|
+
await expect(this.manager.connect(this.caller).execute(this.target, this.calldata))
|
|
2084
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
|
|
2085
|
+
.withArgs(this.caller, this.target, this.calldata.substring(0, 10));
|
|
2086
|
+
});
|
|
2087
|
+
},
|
|
2088
|
+
open: {
|
|
2089
|
+
callerIsTheManager: {
|
|
2090
|
+
executing() {
|
|
2091
|
+
it('succeeds', async function () {
|
|
2092
|
+
await this.manager.connect(this.caller).execute(this.target, this.calldata);
|
|
2093
|
+
});
|
|
2094
|
+
},
|
|
2095
|
+
notExecuting() {
|
|
2096
|
+
it('reverts as AccessManagerUnauthorizedCall', async function () {
|
|
2097
|
+
await expect(this.manager.connect(this.caller).execute(this.target, this.calldata))
|
|
2098
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
|
|
2099
|
+
.withArgs(this.caller, this.target, this.calldata.substring(0, 10));
|
|
2100
|
+
});
|
|
2101
|
+
},
|
|
2102
|
+
},
|
|
2103
|
+
callerIsNotTheManager: {
|
|
2104
|
+
publicRoleIsRequired() {
|
|
2105
|
+
it('succeeds', async function () {
|
|
2106
|
+
await this.manager.connect(this.caller).execute(this.target, this.calldata);
|
|
2107
|
+
});
|
|
2108
|
+
},
|
|
2109
|
+
specificRoleIsRequired: {
|
|
2110
|
+
requiredRoleIsGranted: {
|
|
2111
|
+
roleGrantingIsDelayed: {
|
|
2112
|
+
callerHasAnExecutionDelay: {
|
|
2113
|
+
beforeGrantDelay() {
|
|
2114
|
+
it('reverts as AccessManagerUnauthorizedCall', async function () {
|
|
2115
|
+
await expect(this.manager.connect(this.caller).execute(this.target, this.calldata))
|
|
2116
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
|
|
2117
|
+
.withArgs(this.caller, this.target, this.calldata.substring(0, 10));
|
|
2118
|
+
});
|
|
2119
|
+
},
|
|
2120
|
+
afterGrantDelay: function self() {
|
|
2121
|
+
self.mineDelay = true;
|
|
2122
|
+
|
|
2123
|
+
beforeEach('define schedule delay', function () {
|
|
2124
|
+
this.scheduleIn = time.duration.days(21); // For testAsSchedulableOperation
|
|
2125
|
+
});
|
|
2126
|
+
|
|
2127
|
+
testAsSchedulableOperation(LIKE_COMMON_SCHEDULABLE);
|
|
2128
|
+
},
|
|
2129
|
+
},
|
|
2130
|
+
callerHasNoExecutionDelay: {
|
|
2131
|
+
beforeGrantDelay() {
|
|
2132
|
+
it('reverts as AccessManagerUnauthorizedCall', async function () {
|
|
2133
|
+
await expect(this.manager.connect(this.caller).execute(this.target, this.calldata))
|
|
2134
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
|
|
2135
|
+
.withArgs(this.caller, this.target, this.calldata.substring(0, 10));
|
|
2136
|
+
});
|
|
2137
|
+
},
|
|
2138
|
+
afterGrantDelay: function self() {
|
|
2139
|
+
self.mineDelay = true;
|
|
2140
|
+
|
|
2141
|
+
it('succeeds', async function () {
|
|
2142
|
+
await this.manager.connect(this.caller).execute(this.target, this.calldata);
|
|
2143
|
+
});
|
|
2144
|
+
},
|
|
2145
|
+
},
|
|
2146
|
+
},
|
|
2147
|
+
roleGrantingIsNotDelayed: {
|
|
2148
|
+
callerHasAnExecutionDelay() {
|
|
2149
|
+
beforeEach('define schedule delay', function () {
|
|
2150
|
+
this.scheduleIn = time.duration.days(15); // For testAsSchedulableOperation
|
|
2151
|
+
});
|
|
2152
|
+
|
|
2153
|
+
testAsSchedulableOperation(LIKE_COMMON_SCHEDULABLE);
|
|
2154
|
+
},
|
|
2155
|
+
callerHasNoExecutionDelay() {
|
|
2156
|
+
it('succeeds', async function () {
|
|
2157
|
+
await this.manager.connect(this.caller).execute(this.target, this.calldata);
|
|
2158
|
+
});
|
|
2159
|
+
},
|
|
2160
|
+
},
|
|
2161
|
+
},
|
|
2162
|
+
requiredRoleIsNotGranted() {
|
|
2163
|
+
it('reverts as AccessManagerUnauthorizedCall', async function () {
|
|
2164
|
+
await expect(this.manager.connect(this.caller).execute(this.target, this.calldata))
|
|
2165
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
|
|
2166
|
+
.withArgs(this.caller, this.target, this.calldata.substring(0, 10));
|
|
2167
|
+
});
|
|
2168
|
+
},
|
|
2169
|
+
},
|
|
2170
|
+
},
|
|
2171
|
+
},
|
|
2172
|
+
});
|
|
2173
|
+
});
|
|
2174
|
+
|
|
2175
|
+
it('executes with a delay consuming the scheduled operation', async function () {
|
|
2176
|
+
const delay = time.duration.hours(4);
|
|
2177
|
+
await this.manager.$_grantRole(this.role.id, this.caller, 0, 1); // Execution delay is needed so the operation is consumed
|
|
2178
|
+
|
|
2179
|
+
const { operationId, schedule } = await prepareOperation(this.manager, {
|
|
2180
|
+
caller: this.caller,
|
|
2181
|
+
target: this.target,
|
|
2182
|
+
calldata: this.calldata,
|
|
2183
|
+
delay,
|
|
2184
|
+
});
|
|
2185
|
+
await schedule();
|
|
2186
|
+
await time.increaseBy.timestamp(delay);
|
|
2187
|
+
await expect(this.manager.connect(this.caller).execute(this.target, this.calldata))
|
|
2188
|
+
.to.emit(this.manager, 'OperationExecuted')
|
|
2189
|
+
.withArgs(operationId, 1n);
|
|
2190
|
+
|
|
2191
|
+
expect(await this.manager.getSchedule(operationId)).to.equal(0n);
|
|
2192
|
+
});
|
|
2193
|
+
|
|
2194
|
+
it('executes with no delay consuming a scheduled operation', async function () {
|
|
2195
|
+
const delay = time.duration.hours(4);
|
|
2196
|
+
|
|
2197
|
+
// give caller an execution delay
|
|
2198
|
+
await this.manager.$_grantRole(this.role.id, this.caller, 0, 1);
|
|
2199
|
+
|
|
2200
|
+
const { operationId, schedule } = await prepareOperation(this.manager, {
|
|
2201
|
+
caller: this.caller,
|
|
2202
|
+
target: this.target,
|
|
2203
|
+
calldata: this.calldata,
|
|
2204
|
+
delay,
|
|
2205
|
+
});
|
|
2206
|
+
await schedule();
|
|
2207
|
+
|
|
2208
|
+
// remove the execution delay
|
|
2209
|
+
await this.manager.$_grantRole(this.role.id, this.caller, 0, 0);
|
|
2210
|
+
|
|
2211
|
+
await time.increaseBy.timestamp(delay);
|
|
2212
|
+
await expect(this.manager.connect(this.caller).execute(this.target, this.calldata))
|
|
2213
|
+
.to.emit(this.manager, 'OperationExecuted')
|
|
2214
|
+
.withArgs(operationId, 1n);
|
|
2215
|
+
|
|
2216
|
+
expect(await this.manager.getSchedule(operationId)).to.equal(0n);
|
|
2217
|
+
});
|
|
2218
|
+
|
|
2219
|
+
it('keeps the original _executionId after finishing the call', async function () {
|
|
2220
|
+
const executionIdBefore = await ethers.provider.getStorage(this.manager, EXECUTION_ID_STORAGE_SLOT);
|
|
2221
|
+
await this.manager.connect(this.caller).execute(this.target, this.calldata);
|
|
2222
|
+
const executionIdAfter = await ethers.provider.getStorage(this.manager, EXECUTION_ID_STORAGE_SLOT);
|
|
2223
|
+
expect(executionIdBefore).to.equal(executionIdAfter);
|
|
2224
|
+
});
|
|
2225
|
+
|
|
2226
|
+
it('reverts executing twice', async function () {
|
|
2227
|
+
const delay = time.duration.hours(2);
|
|
2228
|
+
await this.manager.$_grantRole(this.role.id, this.caller, 0, 1); // Execution delay is needed so the operation is consumed
|
|
2229
|
+
|
|
2230
|
+
const { operationId, schedule } = await prepareOperation(this.manager, {
|
|
2231
|
+
caller: this.caller,
|
|
2232
|
+
target: this.target,
|
|
2233
|
+
calldata: this.calldata,
|
|
2234
|
+
delay,
|
|
2235
|
+
});
|
|
2236
|
+
await schedule();
|
|
2237
|
+
await time.increaseBy.timestamp(delay);
|
|
2238
|
+
await this.manager.connect(this.caller).execute(this.target, this.calldata);
|
|
2239
|
+
await expect(this.manager.connect(this.caller).execute(this.target, this.calldata))
|
|
2240
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerNotScheduled')
|
|
2241
|
+
.withArgs(operationId);
|
|
2242
|
+
});
|
|
2243
|
+
});
|
|
2244
|
+
|
|
2245
|
+
describe('#consumeScheduledOp', function () {
|
|
2246
|
+
beforeEach('define scheduling parameters', async function () {
|
|
2247
|
+
const method = this.target.fnRestricted.getFragment();
|
|
2248
|
+
this.caller = await ethers.getSigner(this.target.target);
|
|
2249
|
+
await impersonate(this.caller.address);
|
|
2250
|
+
this.calldata = this.target.interface.encodeFunctionData(method, []);
|
|
2251
|
+
this.role = { id: 9834983n };
|
|
2252
|
+
|
|
2253
|
+
await this.manager.$_setTargetFunctionRole(this.target, method.selector, this.role.id);
|
|
2254
|
+
await this.manager.$_grantRole(this.role.id, this.caller, 0, 1); // nonzero execution delay
|
|
2255
|
+
|
|
2256
|
+
this.scheduleIn = time.duration.hours(10); // For testAsSchedulableOperation
|
|
2257
|
+
});
|
|
2258
|
+
|
|
2259
|
+
describe('when caller is not consuming scheduled operation', function () {
|
|
2260
|
+
beforeEach('set consuming false', async function () {
|
|
2261
|
+
await this.target.setIsConsumingScheduledOp(false, ethers.toBeHex(CONSUMING_SCHEDULE_STORAGE_SLOT, 32));
|
|
2262
|
+
});
|
|
2263
|
+
|
|
2264
|
+
it('reverts as AccessManagerUnauthorizedConsume', async function () {
|
|
2265
|
+
await expect(this.manager.connect(this.caller).consumeScheduledOp(this.caller, this.calldata))
|
|
2266
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedConsume')
|
|
2267
|
+
.withArgs(this.caller);
|
|
2268
|
+
});
|
|
2269
|
+
});
|
|
2270
|
+
|
|
2271
|
+
describe('when caller is consuming scheduled operation', function () {
|
|
2272
|
+
beforeEach('set consuming true', async function () {
|
|
2273
|
+
await this.target.setIsConsumingScheduledOp(true, ethers.toBeHex(CONSUMING_SCHEDULE_STORAGE_SLOT, 32));
|
|
2274
|
+
});
|
|
2275
|
+
|
|
2276
|
+
testAsSchedulableOperation({
|
|
2277
|
+
scheduled: {
|
|
2278
|
+
before() {
|
|
2279
|
+
it('reverts as AccessManagerNotReady', async function () {
|
|
2280
|
+
await expect(this.manager.connect(this.caller).consumeScheduledOp(this.caller, this.calldata))
|
|
2281
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerNotReady')
|
|
2282
|
+
.withArgs(this.operationId);
|
|
2283
|
+
});
|
|
2284
|
+
},
|
|
2285
|
+
after() {
|
|
2286
|
+
it('consumes the scheduled operation and resets timepoint', async function () {
|
|
2287
|
+
expect(await this.manager.getSchedule(this.operationId)).to.equal(this.scheduledAt + this.scheduleIn);
|
|
2288
|
+
|
|
2289
|
+
await expect(this.manager.connect(this.caller).consumeScheduledOp(this.caller, this.calldata))
|
|
2290
|
+
.to.emit(this.manager, 'OperationExecuted')
|
|
2291
|
+
.withArgs(this.operationId, 1n);
|
|
2292
|
+
expect(await this.manager.getSchedule(this.operationId)).to.equal(0n);
|
|
2293
|
+
});
|
|
2294
|
+
},
|
|
2295
|
+
expired() {
|
|
2296
|
+
it('reverts as AccessManagerExpired', async function () {
|
|
2297
|
+
await expect(this.manager.connect(this.caller).consumeScheduledOp(this.caller, this.calldata))
|
|
2298
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerExpired')
|
|
2299
|
+
.withArgs(this.operationId);
|
|
2300
|
+
});
|
|
2301
|
+
},
|
|
2302
|
+
},
|
|
2303
|
+
notScheduled() {
|
|
2304
|
+
it('reverts as AccessManagerNotScheduled', async function () {
|
|
2305
|
+
await expect(this.manager.connect(this.caller).consumeScheduledOp(this.caller, this.calldata))
|
|
2306
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerNotScheduled')
|
|
2307
|
+
.withArgs(this.operationId);
|
|
2308
|
+
});
|
|
2309
|
+
},
|
|
2310
|
+
});
|
|
2311
|
+
});
|
|
2312
|
+
});
|
|
2313
|
+
|
|
2314
|
+
describe('#cancelScheduledOp', function () {
|
|
2315
|
+
beforeEach('setup scheduling', async function () {
|
|
2316
|
+
this.method = this.target.fnRestricted.getFragment();
|
|
2317
|
+
this.caller = this.roles.SOME.members[0];
|
|
2318
|
+
await this.manager.$_setTargetFunctionRole(this.target, this.method.selector, this.roles.SOME.id);
|
|
2319
|
+
await this.manager.$_grantRole(this.roles.SOME.id, this.caller, 0, 1); // nonzero execution delay
|
|
2320
|
+
|
|
2321
|
+
this.calldata = this.target.interface.encodeFunctionData(this.method, []);
|
|
2322
|
+
this.scheduleIn = time.duration.days(10); // For testAsSchedulableOperation
|
|
2323
|
+
});
|
|
2324
|
+
|
|
2325
|
+
testAsSchedulableOperation({
|
|
2326
|
+
scheduled: {
|
|
2327
|
+
before() {
|
|
2328
|
+
describe('when caller is the scheduler', function () {
|
|
2329
|
+
it('succeeds', async function () {
|
|
2330
|
+
await this.manager.connect(this.caller).cancel(this.caller, this.target, this.calldata);
|
|
2331
|
+
});
|
|
2332
|
+
});
|
|
2333
|
+
|
|
2334
|
+
describe('when caller is an admin', function () {
|
|
2335
|
+
it('succeeds', async function () {
|
|
2336
|
+
await this.manager.connect(this.roles.ADMIN.members[0]).cancel(this.caller, this.target, this.calldata);
|
|
2337
|
+
});
|
|
2338
|
+
});
|
|
2339
|
+
|
|
2340
|
+
describe('when caller is the role guardian', function () {
|
|
2341
|
+
it('succeeds', async function () {
|
|
2342
|
+
await this.manager
|
|
2343
|
+
.connect(this.roles.SOME_GUARDIAN.members[0])
|
|
2344
|
+
.cancel(this.caller, this.target, this.calldata);
|
|
2345
|
+
});
|
|
2346
|
+
});
|
|
2347
|
+
|
|
2348
|
+
describe('when caller is any other account', function () {
|
|
2349
|
+
it('reverts as AccessManagerUnauthorizedCancel', async function () {
|
|
2350
|
+
await expect(this.manager.connect(this.other).cancel(this.caller, this.target, this.calldata))
|
|
2351
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCancel')
|
|
2352
|
+
.withArgs(this.other, this.caller, this.target, this.method.selector);
|
|
2353
|
+
});
|
|
2354
|
+
});
|
|
2355
|
+
},
|
|
2356
|
+
after() {
|
|
2357
|
+
it('succeeds', async function () {
|
|
2358
|
+
await this.manager.connect(this.caller).cancel(this.caller, this.target, this.calldata);
|
|
2359
|
+
});
|
|
2360
|
+
},
|
|
2361
|
+
expired() {
|
|
2362
|
+
it('succeeds', async function () {
|
|
2363
|
+
await this.manager.connect(this.caller).cancel(this.caller, this.target, this.calldata);
|
|
2364
|
+
});
|
|
2365
|
+
},
|
|
2366
|
+
},
|
|
2367
|
+
notScheduled() {
|
|
2368
|
+
it('reverts as AccessManagerNotScheduled', async function () {
|
|
2369
|
+
await expect(this.manager.cancel(this.caller, this.target, this.calldata))
|
|
2370
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerNotScheduled')
|
|
2371
|
+
.withArgs(this.operationId);
|
|
2372
|
+
});
|
|
2373
|
+
},
|
|
2374
|
+
});
|
|
2375
|
+
|
|
2376
|
+
it('cancels an operation and resets schedule', async function () {
|
|
2377
|
+
const { operationId, schedule } = await prepareOperation(this.manager, {
|
|
2378
|
+
caller: this.caller,
|
|
2379
|
+
target: this.target,
|
|
2380
|
+
calldata: this.calldata,
|
|
2381
|
+
delay: this.scheduleIn,
|
|
2382
|
+
});
|
|
2383
|
+
await schedule();
|
|
2384
|
+
await expect(this.manager.connect(this.caller).cancel(this.caller, this.target, this.calldata))
|
|
2385
|
+
.to.emit(this.manager, 'OperationCanceled')
|
|
2386
|
+
.withArgs(operationId, 1n);
|
|
2387
|
+
expect(await this.manager.getSchedule(operationId)).to.equal('0');
|
|
2388
|
+
});
|
|
2389
|
+
});
|
|
2390
|
+
|
|
2391
|
+
describe('with Ownable target contract', function () {
|
|
2392
|
+
const roleId = 1n;
|
|
2393
|
+
|
|
2394
|
+
beforeEach(async function () {
|
|
2395
|
+
this.ownable = await ethers.deployContract('$Ownable', [this.manager]);
|
|
2396
|
+
|
|
2397
|
+
// add user to role
|
|
2398
|
+
await this.manager.$_grantRole(roleId, this.user, 0, 0);
|
|
2399
|
+
});
|
|
2400
|
+
|
|
2401
|
+
it('initial state', async function () {
|
|
2402
|
+
expect(await this.ownable.owner()).to.equal(this.manager);
|
|
2403
|
+
});
|
|
2404
|
+
|
|
2405
|
+
describe('Contract is closed', function () {
|
|
2406
|
+
beforeEach(async function () {
|
|
2407
|
+
await this.manager.$_setTargetClosed(this.ownable, true);
|
|
2408
|
+
});
|
|
2409
|
+
|
|
2410
|
+
it('directly call: reverts', async function () {
|
|
2411
|
+
await expect(this.ownable.connect(this.user).$_checkOwner())
|
|
2412
|
+
.to.be.revertedWithCustomError(this.ownable, 'OwnableUnauthorizedAccount')
|
|
2413
|
+
.withArgs(this.user);
|
|
2414
|
+
});
|
|
2415
|
+
|
|
2416
|
+
it('relayed call (with role): reverts', async function () {
|
|
2417
|
+
await expect(
|
|
2418
|
+
this.manager.connect(this.user).execute(this.ownable, this.ownable.$_checkOwner.getFragment().selector),
|
|
2419
|
+
)
|
|
2420
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
|
|
2421
|
+
.withArgs(this.user, this.ownable, this.ownable.$_checkOwner.getFragment().selector);
|
|
2422
|
+
});
|
|
2423
|
+
|
|
2424
|
+
it('relayed call (without role): reverts', async function () {
|
|
2425
|
+
await expect(
|
|
2426
|
+
this.manager.connect(this.other).execute(this.ownable, this.ownable.$_checkOwner.getFragment().selector),
|
|
2427
|
+
)
|
|
2428
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
|
|
2429
|
+
.withArgs(this.other, this.ownable, this.ownable.$_checkOwner.getFragment().selector);
|
|
2430
|
+
});
|
|
2431
|
+
});
|
|
2432
|
+
|
|
2433
|
+
describe('Contract is managed', function () {
|
|
2434
|
+
describe('function is open to specific role', function () {
|
|
2435
|
+
beforeEach(async function () {
|
|
2436
|
+
await this.manager.$_setTargetFunctionRole(
|
|
2437
|
+
this.ownable,
|
|
2438
|
+
this.ownable.$_checkOwner.getFragment().selector,
|
|
2439
|
+
roleId,
|
|
2440
|
+
);
|
|
2441
|
+
});
|
|
2442
|
+
|
|
2443
|
+
it('directly call: reverts', async function () {
|
|
2444
|
+
await expect(this.ownable.connect(this.user).$_checkOwner())
|
|
2445
|
+
.to.be.revertedWithCustomError(this.ownable, 'OwnableUnauthorizedAccount')
|
|
2446
|
+
.withArgs(this.user);
|
|
2447
|
+
});
|
|
2448
|
+
|
|
2449
|
+
it('relayed call (with role): success', async function () {
|
|
2450
|
+
await this.manager.connect(this.user).execute(this.ownable, this.ownable.$_checkOwner.getFragment().selector);
|
|
2451
|
+
});
|
|
2452
|
+
|
|
2453
|
+
it('relayed call (without role): reverts', async function () {
|
|
2454
|
+
await expect(
|
|
2455
|
+
this.manager.connect(this.other).execute(this.ownable, this.ownable.$_checkOwner.getFragment().selector),
|
|
2456
|
+
)
|
|
2457
|
+
.to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
|
|
2458
|
+
.withArgs(this.other, this.ownable, this.ownable.$_checkOwner.getFragment().selector);
|
|
2459
|
+
});
|
|
2460
|
+
});
|
|
2461
|
+
|
|
2462
|
+
describe('function is open to public role', function () {
|
|
2463
|
+
beforeEach(async function () {
|
|
2464
|
+
await this.manager.$_setTargetFunctionRole(
|
|
2465
|
+
this.ownable,
|
|
2466
|
+
this.ownable.$_checkOwner.getFragment().selector,
|
|
2467
|
+
this.roles.PUBLIC.id,
|
|
2468
|
+
);
|
|
2469
|
+
});
|
|
2470
|
+
|
|
2471
|
+
it('directly call: reverts', async function () {
|
|
2472
|
+
await expect(this.ownable.connect(this.user).$_checkOwner())
|
|
2473
|
+
.to.be.revertedWithCustomError(this.ownable, 'OwnableUnauthorizedAccount')
|
|
2474
|
+
.withArgs(this.user);
|
|
2475
|
+
});
|
|
2476
|
+
|
|
2477
|
+
it('relayed call (with role): success', async function () {
|
|
2478
|
+
await this.manager.connect(this.user).execute(this.ownable, this.ownable.$_checkOwner.getFragment().selector);
|
|
2479
|
+
});
|
|
2480
|
+
|
|
2481
|
+
it('relayed call (without role): success', async function () {
|
|
2482
|
+
await this.manager
|
|
2483
|
+
.connect(this.other)
|
|
2484
|
+
.execute(this.ownable, this.ownable.$_checkOwner.getFragment().selector);
|
|
2485
|
+
});
|
|
2486
|
+
});
|
|
2487
|
+
});
|
|
2488
|
+
});
|
|
2489
|
+
});
|