Compare commits
47 Commits
audit-v5.1
...
release-v5
| Author | SHA1 | Date | |
|---|---|---|---|
| dbb6104ce8 | |||
| 26b4b60999 | |||
| d4ec2782b7 | |||
| f7bb9881a8 | |||
| e53f81b704 | |||
| 01ef448981 | |||
| 9ce0340466 | |||
| 4eb67a408c | |||
| 83330a6e4c | |||
| ab967b8639 | |||
| a34d986eca | |||
| 5161a4dc8a | |||
| 932fddf69a | |||
| 73995884f3 | |||
| 12735415d6 | |||
| d27635fc67 | |||
| cff043486b | |||
| 6a0cfcedf0 | |||
| bd25a0a26f | |||
| 228013d232 | |||
| a874080fc1 | |||
| 3e45ab2d51 | |||
| 37f0b3b2ce | |||
| e49fcbeb56 | |||
| 21ef8130c8 | |||
| d6954f17b5 | |||
| 51191d3152 | |||
| a14d8149ed | |||
| 7a4064d886 | |||
| bf629d4ea7 | |||
| aef22bddc9 | |||
| bc96591f65 | |||
| fb2aec6946 | |||
| 322df4226d | |||
| 4ce98d75bf | |||
| 3a1e1bd336 | |||
| 57c84f6bb8 | |||
| 8f3f4f7f17 | |||
| 621fc0fe99 | |||
| 011c8bb034 | |||
| 53f2721e8c | |||
| b805cc82d3 | |||
| 33894d2a5b | |||
| 9aaca67aa6 | |||
| abcec9e4a3 | |||
| b55b47d421 | |||
| 0d6703b852 |
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ERC1155Receiver`: Removed in favor of `ERC1155Holder`.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`TimelockController`: Changed the role architecture to use `DEFAULT_ADMIN_ROLE` as the admin for all roles, instead of the bespoke `TIMELOCK_ADMIN_ROLE` that was used previously. This aligns with the general recommendation for `AccessControl` and makes the addition of new roles easier. Accordingly, the `admin` parameter and timelock will now be granted `DEFAULT_ADMIN_ROLE` instead of `TIMELOCK_ADMIN_ROLE`. ([#3799](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3799))
|
||||
@ -1,4 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
Use `abi.encodeCall` in place of `abi.encodeWithSelector` and `abi.encodeWithSignature` for improved type-checking of parameters
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ERC2771Forwarder`: Added `deadline` for expiring transactions, batching, and more secure handling of `msg.value`.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`Math`: Make `ceilDiv` to revert on 0 division even if the numerator is 0
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`Governor`: Refactored internals to implement common queuing logic in the core module of the Governor. Added `queue` and `_queueOperations` functions that act at different levels. Modules that implement queuing via timelocks are expected to override `_queueOperations` to implement the timelock-specific logic. Added `_executeOperations` as the equivalent for execution.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ERC20`, `ERC721`, `ERC1155`: Deleted `_beforeTokenTransfer` and `_afterTokenTransfer` hooks, added a new internal `_update` function for customizations, and refactored all extensions using those hooks to use `_update` instead. ([#3838](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3838), [#3876](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3876), [#4377](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4377))
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ERC1155Supply`: add a `totalSupply()` function that returns the total amount of token circulating, this change will restrict the total tokens minted across all ids to 2\*\*256-1 .
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`Ownable`: Prevent using address(0) as the initial owner.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`Ownable`: Add an `initialOwner` parameter to the constructor, making the ownership initialization explicit.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`Proxy`: Removed redundant `receive` function.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
Optimize `Strings.equal`
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ERC721`: `_approve` no longer allows approving the owner of the tokenId. `_setApprovalForAll` no longer allows setting address(0) as an operator.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ERC721URIStorage`: Allow setting the token URI prior to minting.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`UUPSUpgradeable`, `TransparentUpgradeableProxy` and `ProxyAdmin`: Removed `upgradeTo` and `upgrade` functions, and made `upgradeToAndCall` and `upgradeAndCall` ignore the data argument if it is empty. It is no longer possible to invoke the receive function (or send value with empty data) along with an upgrade.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ERC721URIStorage`, `ERC721Royalty`: Stop resetting token-specific URI and royalties when burning.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`Address`: Removed the ability to customize error messages. A common custom error is always used if the underlying revert reason cannot be bubbled up.
|
||||
@ -1,7 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
Replace some uses of `abi.encodePacked` with clearer alternatives (e.g. `bytes.concat`, `string.concat`). (#4504)[https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4504]
|
||||
|
||||
pr: #4296
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`Arrays`: Optimize `findUpperBound` by removing redundant SLOAD.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`ECDSA`: Use unchecked arithmetic for the `tryRecover` function that receives the `r` and `vs` short-signature fields separately.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`Checkpoints`: library moved from `utils` to `utils/structs`
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`SafeERC20`: Removed `safePermit` in favor of documentation-only `permit` recommendations.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`Governor`: Optimized use of storage for proposal data
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ERC1967Utils`: Refactor the `ERC1967Upgrade` abstract contract as a library.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`TransparentUpgradeableProxy`: Admin is now stored in an immutable variable (set during construction) to avoid unnecessary storage reads on every proxy call. This removed the ability to ever change the admin. Transfer of the upgrade capability is exclusively handled through the ownership of the `ProxyAdmin`.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`VestingWallet`: Use `Ownable` instead of an immutable `beneficiary`.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ERC20`: Remove `Approval` event previously emitted in `transferFrom` to indicate that part of the allowance was consumed. With this change, allowances are no longer reconstructible from events. See the code for guidelines on how to re-enable this event if needed.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
Move the logic to validate ERC-1822 during an upgrade from `ERC1967Utils` to `UUPSUpgradeable`.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`VestingWallet`: Fix revert during 1 second time window when duration is 0.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`Arrays`: Add `unsafeMemoryAccess` helpers to read from a memory array without checking the length.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`MessageHashUtils`: Add a new library for creating message digest to be used along with signing or recovery such as ECDSA or ERC-1271. These functions are moved from the `ECDSA` library.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`GovernorTimelockControl`: Clean up timelock id on execution for gas refund.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`MerkleProof`: Use custom error to report invalid multiproof instead of reverting with overflow panic.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`Initializable`: Use intermediate variables to improve readability.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`EIP712`: Add internal getters for the name and version strings
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`TimelockController`: Add a state getter that returns an `OperationState` enum.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
Replace revert strings and require statements with custom errors.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`Nonces`: Added a new contract to keep track of user nonces. Used for signatures in `ERC20Permit`, `ERC20Votes`, and `ERC721Votes`. ([#3816](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3816))
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`Governor`: Add validation in ERC1155 and ERC721 receiver hooks to ensure Governor is the executor.
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
Switched to using explicit Solidity import statements. Some previously available symbols may now have to be separately imported.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`Math`: Optimized stack operations in `mulDiv`.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`Governor`: Add support for casting votes with ERC-1271 signatures by using a `bytes memory signature` instead of `r`, `s` and `v` arguments in the `castVoteBySig` and `castVoteWithReasonAndParamsBySig` functions.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`BeaconProxy`: Use an immutable variable to store the address of the beacon. It is no longer possible for a `BeaconProxy` to upgrade by changing to another beacon.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ERC721`: Renamed `_requireMinted` to `_requireOwned` and added a return value with the current owner. Implemented `ownerOf` in terms of `_requireOwned`.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`GovernorTimelockControl`: Add the Governor instance address as part of the TimelockController operation `salt` to avoid operation id collisions between governors using the same TimelockController.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`AccessManager`: Added a new contract for managing access control of complex systems in a consolidated location.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
Overrides are now used internally for a number of functions that were previously hardcoded to their default implementation in certain locations: `ERC1155Supply.totalSupply`, `ERC721.ownerOf`, `ERC721.balanceOf` and `ERC721.totalSupply` in `ERC721Enumerable`, `ERC20.totalSupply` in `ERC20FlashMint`, and `ERC1967._getImplementation` in `ERC1967Proxy`.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ProxyAdmin`: Removed `getProxyAdmin` and `getProxyImplementation` getters. ([#3820](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3820))
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`ERC1155`: Optimize array allocation.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
Bump minimum compiler version required to 0.8.20
|
||||
@ -1,7 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ERC20Votes`: Changed internal vote accounting to reusable `Votes` module previously used by `ERC721Votes`. Removed implicit `ERC20Permit` inheritance. Note that the `DOMAIN_SEPARATOR` getter was previously guaranteed to be available for `ERC20Votes` contracts, but is no longer available unless `ERC20Permit` is explicitly used; ERC-5267 support is included in `ERC20Votes` with `EIP712` and is recommended as an alternative.
|
||||
|
||||
pr: #3816
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ERC20`: Remove the non-standard `increaseAllowance` and `decreaseAllowance` functions.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`Governor`: Add `voter` and `nonce` parameters in signed ballots, to avoid forging signatures for random addresses, prevent signature replay, and allow invalidating signatures. Add `voter` as a new parameter in the `castVoteBySig` and `castVoteWithReasonAndParamsBySig` functions.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`TransparentUpgradeableProxy`: Removed `admin` and `implementation` getters, which were only callable by the proxy owner and thus not very useful. ([#3820](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3820))
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ERC1155`: Remove check for address zero in `balanceOf`.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ReentrancyGuard`, `Pausable`: Moved to `utils` directory.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`access`: Move `AccessControl` extensions to a dedicated directory.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`ERC721Consecutive`: Add a `_firstConsecutiveId` internal function that can be overridden to change the id of the first token minted through `_mintConsecutive`.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`DoubleEndedQueue`: refactor internal structure to use `uint128` instead of `int128`. This has no effect on the library interface.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`Governor`: Add a mechanism to restrict the address of the proposer using a suffix in the description.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`Governor`, `Initializable`, and `UUPSUpgradeable`: Use internal functions in modifiers to optimize bytecode size.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`Strings`: Rename `toString(int256)` to `toStringSigned(int256)`.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`BeaconProxy`: Reject value in initialization unless a payable function is explicitly invoked.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`Initializable`: Use the namespaced storage pattern to avoid putting critical variables in slot 0. Allow reinitializer versions greater than 256.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`ERC1155`: Bubble errors triggered in the `onERC1155Received` and `onERC1155BatchReceived` hooks.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`ERC1155`: Optimize array accesses by skipping bounds checking when unnecessary.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`AccessControl`: Add a boolean return value to the internal `_grantRole` and `_revokeRole` functions indicating whether the role was granted or revoked.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`ERC2771Context`: Return the forwarder address whenever the `msg.data` of a call originating from a trusted forwarder is not long enough to contain the request signer address (i.e. `msg.data.length` is less than 20 bytes), as specified by ERC-2771.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
Remove the `override` specifier from functions that only override a single interface function.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`GovernorTimelockAccess`: Added a module to connect a governor with an instance of `AccessManager`, allowing the governor to make calls that are delay-restricted by the manager using the normal `queue` workflow.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`ERC2771Context`: Prevent revert in `_msgData()` when a call originating from a trusted forwarder is not long enough to contain the request signer address (i.e. `msg.data.length` is less than 20 bytes). Return the full calldata in that case.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
Upgradeable contracts now use namespaced storage (EIP-7201).
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`GovernorStorage`: Added a new governor extension that stores the proposal details in storage, with an interface that operates on `proposalId`, as well as proposal enumerability. This replaces the old `GovernorCompatibilityBravo` module.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`Votes`: Use Trace208 for checkpoints. This enables EIP-6372 clock support for keys but reduces the max supported voting power to uint208.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`Math`: Renamed members of `Rounding` enum, and added a new rounding mode for "away from zero".
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`SafeERC20`: Refactor `safeDecreaseAllowance` and `safeIncreaseAllowance` to support USDT-like tokens.
|
||||
6
.github/actions/setup/action.yml
vendored
6
.github/actions/setup/action.yml
vendored
@ -15,5 +15,7 @@ runs:
|
||||
run: npm ci
|
||||
shell: bash
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
env:
|
||||
SKIP_COMPILE: true
|
||||
- name: Install Foundry
|
||||
uses: foundry-rs/foundry-toolchain@v1
|
||||
with:
|
||||
version: nightly
|
||||
|
||||
10
.github/workflows/checks.yml
vendored
10
.github/workflows/checks.yml
vendored
@ -56,6 +56,10 @@ jobs:
|
||||
fetch-depth: 0 # Include history so patch conflicts are resolved automatically
|
||||
- name: Set up environment
|
||||
uses: ./.github/actions/setup
|
||||
- name: Copy non-upgradeable contracts as dependency
|
||||
run: |
|
||||
mkdir -p lib/openzeppelin-contracts
|
||||
cp -rnT contracts lib/openzeppelin-contracts/contracts
|
||||
- name: Transpile to upgradeable
|
||||
run: bash scripts/upgradeable/transpile.sh
|
||||
- name: Run tests
|
||||
@ -75,10 +79,8 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install Foundry
|
||||
uses: foundry-rs/foundry-toolchain@v1
|
||||
with:
|
||||
version: nightly
|
||||
- name: Set up environment
|
||||
uses: ./.github/actions/setup
|
||||
- name: Run tests
|
||||
run: forge test -vv
|
||||
|
||||
|
||||
4
.github/workflows/release-cycle.yml
vendored
4
.github/workflows/release-cycle.yml
vendored
@ -147,16 +147,12 @@ jobs:
|
||||
with:
|
||||
name: ${{ github.ref_name }}
|
||||
path: ${{ steps.pack.outputs.tarball }}
|
||||
- name: Tag
|
||||
run: npx changeset tag
|
||||
- name: Publish
|
||||
run: bash scripts/release/workflow/publish.sh
|
||||
env:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
TARBALL: ${{ steps.pack.outputs.tarball }}
|
||||
TAG: ${{ steps.pack.outputs.tag }}
|
||||
- name: Push tags
|
||||
run: git push --tags
|
||||
- name: Create Github Release
|
||||
uses: actions/github-script@v6
|
||||
env:
|
||||
|
||||
6
.github/workflows/upgradeable.yml
vendored
6
.github/workflows/upgradeable.yml
vendored
@ -18,13 +18,17 @@ jobs:
|
||||
token: ${{ secrets.GH_TOKEN_UPGRADEABLE }}
|
||||
- name: Fetch current non-upgradeable branch
|
||||
run: |
|
||||
git fetch "https://github.com/${{ github.repository }}.git" "$REF"
|
||||
git fetch "$REMOTE" master # Fetch default branch first for patch to apply cleanly
|
||||
git fetch "$REMOTE" "$REF"
|
||||
git checkout FETCH_HEAD
|
||||
env:
|
||||
REF: ${{ github.ref }}
|
||||
REMOTE: https://github.com/${{ github.repository }}.git
|
||||
- name: Set up environment
|
||||
uses: ./.github/actions/setup
|
||||
- run: bash scripts/git-user-config.sh
|
||||
- name: Transpile to upgradeable
|
||||
run: bash scripts/upgradeable/transpile-onto.sh ${{ github.ref_name }} origin/${{ github.ref_name }}
|
||||
env:
|
||||
SUBMODULE_REMOTE: https://github.com/${{ github.repository }}.git
|
||||
- run: git push origin ${{ github.ref_name }}
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -63,6 +63,7 @@ contracts-exposed
|
||||
|
||||
# Foundry
|
||||
/out
|
||||
/cache_forge
|
||||
|
||||
# Certora
|
||||
.certora*
|
||||
|
||||
256
CHANGELOG.md
256
CHANGELOG.md
@ -1,12 +1,35 @@
|
||||
# Changelog
|
||||
|
||||
## Unreleased
|
||||
|
||||
> **Warning** Version 5.0 is under active development and should not be used. Install the releases from npm or use the version tags in the repository.
|
||||
## 5.0.2 (2024-02-29)
|
||||
|
||||
### Removals
|
||||
- `Base64`: Fix issue where dirty memory located just after the input buffer is affecting the result. ([#4926](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4926))
|
||||
|
||||
The following contracts, libraries and functions were removed:
|
||||
## 5.0.1 (2023-12-07)
|
||||
|
||||
- `ERC2771Context` and `Context`: Introduce a `_contextPrefixLength()` getter, used to trim extra information appended to `msg.data`.
|
||||
- `Multicall`: Make aware of non-canonical context (i.e. `msg.sender` is not `_msgSender()`), allowing compatibility with `ERC2771Context`.
|
||||
|
||||
## 5.0.0 (2023-10-05)
|
||||
|
||||
### Additions Summary
|
||||
|
||||
The following contracts and libraries were added:
|
||||
|
||||
- `AccessManager`: A consolidated system for managing access control in complex systems.
|
||||
- `AccessManaged`: A module for connecting a contract to an authority in charge of its access control.
|
||||
- `GovernorTimelockAccess`: An adapter for time-locking governance proposals using an `AccessManager`.
|
||||
- `AuthorityUtils`: A library of utilities for interacting with authority contracts.
|
||||
- `GovernorStorage`: A Governor module that stores proposal details in storage.
|
||||
- `ERC2771Forwarder`: An ERC2771 forwarder for meta transactions.
|
||||
- `ERC1967Utils`: A library with ERC1967 events, errors and getters.
|
||||
- `Nonces`: An abstraction for managing account nonces.
|
||||
- `MessageHashUtils`: A library for producing digests for ECDSA operations.
|
||||
- `Time`: A library with helpers for manipulating time-related objects.
|
||||
|
||||
### Removals Summary
|
||||
|
||||
The following contracts, libraries, and functions were removed:
|
||||
|
||||
- `Address.isContract` (because of its ambiguous nature and potential for misuse)
|
||||
- `Checkpoints.History`
|
||||
@ -30,51 +53,236 @@ The following contracts, libraries and functions were removed:
|
||||
|
||||
These removals were implemented in the following PRs: [#3637](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3637), [#3880](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3880), [#3945](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3945), [#4258](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4258), [#4276](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4276), [#4289](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4289)
|
||||
|
||||
### How to upgrade from 4.x
|
||||
### Changes by category
|
||||
|
||||
#### General
|
||||
|
||||
- Replaced revert strings and require statements with custom errors. ([#4261](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4261))
|
||||
- Bumped minimum compiler version required to 0.8.20 ([#4288](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4288))
|
||||
- Use of `abi.encodeCall` in place of `abi.encodeWithSelector` and `abi.encodeWithSignature` for improved type-checking of parameters ([#4293](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4293))
|
||||
- Replaced some uses of `abi.encodePacked` with clearer alternatives (e.g. `bytes.concat`, `string.concat`). ([#4504](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4504)) ([#4296](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4296))
|
||||
- Overrides are now used internally for a number of functions that were previously hardcoded to their default implementation in certain locations: `ERC1155Supply.totalSupply`, `ERC721.ownerOf`, `ERC721.balanceOf` and `ERC721.totalSupply` in `ERC721Enumerable`, `ERC20.totalSupply` in `ERC20FlashMint`, and `ERC1967._getImplementation` in `ERC1967Proxy`. ([#4299](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4299))
|
||||
- Removed the `override` specifier from functions that only override a single interface function. ([#4315](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4315))
|
||||
- Switched to using explicit Solidity import statements. Some previously available symbols may now have to be separately imported. ([#4399](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4399))
|
||||
- `Governor`, `Initializable`, and `UUPSUpgradeable`: Use internal functions in modifiers to optimize bytecode size. ([#4472](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4472))
|
||||
- Upgradeable contracts now use namespaced storage (EIP-7201). ([#4534](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4534))
|
||||
- Upgradeable contracts no longer transpile interfaces and libraries. ([#4628](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4628))
|
||||
|
||||
#### Access
|
||||
|
||||
- `Ownable`: Added an `initialOwner` parameter to the constructor, making the ownership initialization explicit. ([#4267](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4267))
|
||||
- `Ownable`: Prevent using address(0) as the initial owner. ([#4531](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4531))
|
||||
- `AccessControl`: Added a boolean return value to the internal `_grantRole` and `_revokeRole` functions indicating whether the role was granted or revoked. ([#4241](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4241))
|
||||
- `access`: Moved `AccessControl` extensions to a dedicated directory. ([#4359](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4359))
|
||||
- `AccessManager`: Added a new contract for managing access control of complex systems in a consolidated location. ([#4121](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4121))
|
||||
- `AccessManager`, `AccessManaged`, `GovernorTimelockAccess`: Ensure that calldata shorter than 4 bytes is not padded to 4 bytes. ([#4624](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4624))
|
||||
- `AccessManager`: Use named return parameters in functions that return multiple values. ([#4624](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4624))
|
||||
- `AccessManager`: Make `schedule` and `execute` more conservative when delay is 0. ([#4644](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4644))
|
||||
|
||||
#### Finance
|
||||
|
||||
- `VestingWallet`: Fixed revert during 1 second time window when duration is 0. ([#4502](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4502))
|
||||
- `VestingWallet`: Use `Ownable` instead of an immutable `beneficiary`. ([#4508](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4508))
|
||||
|
||||
#### Governance
|
||||
|
||||
- `Governor`: Optimized use of storage for proposal data ([#4268](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4268))
|
||||
- `Governor`: Added validation in ERC1155 and ERC721 receiver hooks to ensure Governor is the executor. ([#4314](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4314))
|
||||
- `Governor`: Refactored internals to implement common queuing logic in the core module of the Governor. Added `queue` and `_queueOperations` functions that act at different levels. Modules that implement queuing via timelocks are expected to override `_queueOperations` to implement the timelock-specific logic. Added `_executeOperations` as the equivalent for execution. ([#4360](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4360))
|
||||
- `Governor`: Added `voter` and `nonce` parameters in signed ballots, to avoid forging signatures for random addresses, prevent signature replay, and allow invalidating signatures. Add `voter` as a new parameter in the `castVoteBySig` and `castVoteWithReasonAndParamsBySig` functions. ([#4378](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4378))
|
||||
- `Governor`: Added support for casting votes with ERC-1271 signatures by using a `bytes memory signature` instead of `r`, `s` and `v` arguments in the `castVoteBySig` and `castVoteWithReasonAndParamsBySig` functions. ([#4418](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4418))
|
||||
- `Governor`: Added a mechanism to restrict the address of the proposer using a suffix in the description.
|
||||
- `GovernorStorage`: Added a new governor extension that stores the proposal details in storage, with an interface that operates on `proposalId`, as well as proposal enumerability. This replaces the old `GovernorCompatibilityBravo` module. ([#4360](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4360))
|
||||
- `GovernorTimelockAccess`: Added a module to connect a governor with an instance of `AccessManager`, allowing the governor to make calls that are delay-restricted by the manager using the normal `queue` workflow. ([#4523](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4523))
|
||||
- `GovernorTimelockControl`: Clean up timelock id on execution for gas refund. ([#4118](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4118))
|
||||
- `GovernorTimelockControl`: Added the Governor instance address as part of the TimelockController operation `salt` to avoid operation id collisions between governors using the same TimelockController. ([#4432](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4432))
|
||||
- `TimelockController`: Changed the role architecture to use `DEFAULT_ADMIN_ROLE` as the admin for all roles, instead of the bespoke `TIMELOCK_ADMIN_ROLE` that was used previously. This aligns with the general recommendation for `AccessControl` and makes the addition of new roles easier. Accordingly, the `admin` parameter and timelock will now be granted `DEFAULT_ADMIN_ROLE` instead of `TIMELOCK_ADMIN_ROLE`. ([#3799](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3799))
|
||||
- `TimelockController`: Added a state getter that returns an `OperationState` enum. ([#4358](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4358))
|
||||
- `Votes`: Use Trace208 for checkpoints. This enables EIP-6372 clock support for keys but reduces the max supported voting power to uint208. ([#4539](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4539))
|
||||
|
||||
#### Metatx
|
||||
|
||||
- `ERC2771Forwarder`: Added `deadline` for expiring transactions, batching, and more secure handling of `msg.value`. ([#4346](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4346))
|
||||
- `ERC2771Context`: Return the forwarder address whenever the `msg.data` of a call originating from a trusted forwarder is not long enough to contain the request signer address (i.e. `msg.data.length` is less than 20 bytes), as specified by ERC-2771. ([#4481](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4481))
|
||||
- `ERC2771Context`: Prevent revert in `_msgData()` when a call originating from a trusted forwarder is not long enough to contain the request signer address (i.e. `msg.data.length` is less than 20 bytes). Return the full calldata in that case. ([#4484](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4484))
|
||||
|
||||
#### Proxy
|
||||
|
||||
- `ProxyAdmin`: Removed `getProxyAdmin` and `getProxyImplementation` getters. ([#3820](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3820))
|
||||
- `TransparentUpgradeableProxy`: Removed `admin` and `implementation` getters, which were only callable by the proxy owner and thus not very useful. ([#3820](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3820))
|
||||
- `ERC1967Utils`: Refactored the `ERC1967Upgrade` abstract contract as a library. ([#4325](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4325))
|
||||
- `TransparentUpgradeableProxy`: Admin is now stored in an immutable variable (set during construction) to avoid unnecessary storage reads on every proxy call. This removed the ability to ever change the admin. Transfer of the upgrade capability is exclusively handled through the ownership of the `ProxyAdmin`. ([#4354](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4354))
|
||||
- Moved the logic to validate ERC-1822 during an upgrade from `ERC1967Utils` to `UUPSUpgradeable`. ([#4356](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4356))
|
||||
- `UUPSUpgradeable`, `TransparentUpgradeableProxy` and `ProxyAdmin`: Removed `upgradeTo` and `upgrade` functions, and made `upgradeToAndCall` and `upgradeAndCall` ignore the data argument if it is empty. It is no longer possible to invoke the receive function (or send value with empty data) along with an upgrade. ([#4382](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4382))
|
||||
- `BeaconProxy`: Reject value in initialization unless a payable function is explicitly invoked. ([#4382](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4382))
|
||||
- `Proxy`: Removed redundant `receive` function. ([#4434](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4434))
|
||||
- `BeaconProxy`: Use an immutable variable to store the address of the beacon. It is no longer possible for a `BeaconProxy` to upgrade by changing to another beacon. ([#4435](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4435))
|
||||
- `Initializable`: Use the namespaced storage pattern to avoid putting critical variables in slot 0. Allow reinitializer versions greater than 256. ([#4460](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4460))
|
||||
- `Initializable`: Use intermediate variables to improve readability. ([#4576](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4576))
|
||||
|
||||
#### Token
|
||||
|
||||
- `ERC20`, `ERC721`, `ERC1155`: Deleted `_beforeTokenTransfer` and `_afterTokenTransfer` hooks, added a new internal `_update` function for customizations, and refactored all extensions using those hooks to use `_update` instead. ([#3838](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3838), [#3876](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3876), [#4377](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4377))
|
||||
- `ERC20`: Removed `Approval` event previously emitted in `transferFrom` to indicate that part of the allowance was consumed. With this change, allowances are no longer reconstructible from events. See the code for guidelines on how to re-enable this event if needed. ([#4370](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4370))
|
||||
- `ERC20`: Removed the non-standard `increaseAllowance` and `decreaseAllowance` functions. ([#4585](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4585))
|
||||
- `ERC20Votes`: Changed internal vote accounting to reusable `Votes` module previously used by `ERC721Votes`. Removed implicit `ERC20Permit` inheritance. Note that the `DOMAIN_SEPARATOR` getter was previously guaranteed to be available for `ERC20Votes` contracts, but is no longer available unless `ERC20Permit` is explicitly used; ERC-5267 support is included in `ERC20Votes` with `EIP712` and is recommended as an alternative. ([#3816](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3816))
|
||||
- `SafeERC20`: Refactored `safeDecreaseAllowance` and `safeIncreaseAllowance` to support USDT-like tokens. ([#4260](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4260))
|
||||
- `SafeERC20`: Removed `safePermit` in favor of documentation-only `permit` recommendations. Based on recommendations from @trust1995 ([#4582](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4582))
|
||||
- `ERC721`: `_approve` no longer allows approving the owner of the tokenId. ([#4377](https://github.com/OpenZeppelin/openzeppelin-contracts/issues/4377)) `_setApprovalForAll` no longer allows setting address(0) as an operator. ([#4377](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4377))
|
||||
- `ERC721`: Renamed `_requireMinted` to `_requireOwned` and added a return value with the current owner. Implemented `ownerOf` in terms of `_requireOwned`. ([#4566](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4566))
|
||||
- `ERC721Consecutive`: Added a `_firstConsecutiveId` internal function that can be overridden to change the id of the first token minted through `_mintConsecutive`. ([#4097](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4097))
|
||||
- `ERC721URIStorage`: Allow setting the token URI prior to minting. ([#4559](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4559))
|
||||
- `ERC721URIStorage`, `ERC721Royalty`: Stop resetting token-specific URI and royalties when burning. ([#4561](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4561))
|
||||
- `ERC1155`: Optimized array allocation. ([#4196](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4196))
|
||||
- `ERC1155`: Removed check for address zero in `balanceOf`. ([#4263](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4263))
|
||||
- `ERC1155`: Optimized array accesses by skipping bounds checking when unnecessary. ([#4300](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4300))
|
||||
- `ERC1155`: Bubble errors triggered in the `onERC1155Received` and `onERC1155BatchReceived` hooks. ([#4314](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4314))
|
||||
- `ERC1155Supply`: Added a `totalSupply()` function that returns the total amount of token circulating, this change will restrict the total tokens minted across all ids to 2\*\*256-1 . ([#3962](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3962))
|
||||
- `ERC1155Receiver`: Removed in favor of `ERC1155Holder`. ([#4450](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4450))
|
||||
|
||||
#### Utils
|
||||
|
||||
- `Address`: Removed the ability to customize error messages. A common custom error is always used if the underlying revert reason cannot be bubbled up. ([#4502](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4502))
|
||||
- `Arrays`: Added `unsafeMemoryAccess` helpers to read from a memory array without checking the length. ([#4300](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4300))
|
||||
- `Arrays`: Optimized `findUpperBound` by removing redundant SLOAD. ([#4442](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4442))
|
||||
- `Checkpoints`: Library moved from `utils` to `utils/structs` ([#4275](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4275))
|
||||
- `DoubleEndedQueue`: Refactored internal structure to use `uint128` instead of `int128`. This has no effect on the library interface. ([#4150](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4150))
|
||||
- `ECDSA`: Use unchecked arithmetic for the `tryRecover` function that receives the `r` and `vs` short-signature fields separately. ([#4301](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4301))
|
||||
- `EIP712`: Added internal getters for the name and version strings ([#4303](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4303))
|
||||
- `Math`: Makes `ceilDiv` to revert on 0 division even if the numerator is 0 ([#4348](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4348))
|
||||
- `Math`: Optimized stack operations in `mulDiv`. ([#4494](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4494))
|
||||
- `Math`: Renamed members of `Rounding` enum, and added a new rounding mode for "away from zero". ([#4455](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4455))
|
||||
- `MerkleProof`: Use custom error to report invalid multiproof instead of reverting with overflow panic. ([#4564](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4564))
|
||||
- `MessageHashUtils`: Added a new library for creating message digest to be used along with signing or recovery such as ECDSA or ERC-1271. These functions are moved from the `ECDSA` library. ([#4430](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4430))
|
||||
- `Nonces`: Added a new contract to keep track of user nonces. Used for signatures in `ERC20Permit`, `ERC20Votes`, and `ERC721Votes`. ([#3816](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3816))
|
||||
- `ReentrancyGuard`, `Pausable`: Moved to `utils` directory. ([#4551](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4551))
|
||||
- `Strings`: Renamed `toString(int256)` to `toStringSigned(int256)`. ([#4330](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4330))
|
||||
- Optimized `Strings.equal` ([#4262](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4262))
|
||||
|
||||
### How to migrate from 4.x
|
||||
|
||||
#### ERC20, ERC721, and ERC1155
|
||||
|
||||
These breaking changes will require modifications to ERC20, ERC721, and ERC1155 contracts, since the `_afterTokenTransfer` and `_beforeTokenTransfer` functions were removed. Any customization made through those hooks should now be done overriding the new `_update` function instead.
|
||||
These breaking changes will require modifications to ERC20, ERC721, and ERC1155 contracts, since the `_afterTokenTransfer` and `_beforeTokenTransfer` functions were removed. Thus, any customization made through those hooks should now be done overriding the new `_update` function instead.
|
||||
|
||||
Minting and burning are implemented by `_update` and customizations should be done by overriding this function as well. `_transfer`, `_mint` and `_burn` are no longer virtual (meaning they are not overridable) to guard against possible inconsistencies.
|
||||
|
||||
For example, a contract using `ERC20`'s `_beforeTokenTransfer` hook would have to be changed in the following way.
|
||||
|
||||
```diff
|
||||
- function _beforeTokenTransfer(
|
||||
+ function _update(
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
) internal virtual override {
|
||||
- super._beforeTokenTransfer(from, to, amount);
|
||||
require(!condition(), "ERC20: wrong condition");
|
||||
+ super._update(from, to, amount);
|
||||
}
|
||||
-function _beforeTokenTransfer(
|
||||
+function _update(
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
) internal virtual override {
|
||||
- super._beforeTokenTransfer(from, to, amount);
|
||||
require(!condition(), "ERC20: wrong condition");
|
||||
+ super._update(from, to, amount);
|
||||
}
|
||||
```
|
||||
|
||||
### More about ERC721
|
||||
#### More about ERC721
|
||||
|
||||
In the case of `ERC721`, the `_update` function does not include a `from` parameter, as the sender is implicitly the previous owner of the `tokenId`. The address of
|
||||
this previous owner is returned by the `_update` function, so it can be used for a posteriori checks. In addition to `to` and `tokenId`, a third parameter (`auth`) is
|
||||
present in this function. This parameter enabled an optional check that the caller/spender is approved to do the transfer. This check cannot be performed after the transfer (because the transfer resets the approval), and doing it before `_update` would require a duplicate call to `_ownerOf`.
|
||||
In the case of `ERC721`, the `_update` function does not include a `from` parameter, as the sender is implicitly the previous owner of the `tokenId`. The address of this previous owner is returned by the `_update` function, so it can be used for a posteriori checks. In addition to `to` and `tokenId`, a third parameter (`auth`) is present in this function. This parameter enabled an optional check that the caller/spender is approved to do the transfer. This check cannot be performed after the transfer (because the transfer resets the approval), and doing it before `_update` would require a duplicate call to `_ownerOf`.
|
||||
|
||||
In this logic of removing hidden SLOADs, the `_isApprovedOrOwner` function was removed in favor of a new `_isAuthorized` function. Overrides that used to target the
|
||||
`_isApprovedOrOwner` should now be performed on the `_isAuthorized` function. Calls to `_isApprovedOrOwner` that preceded a call to `_transfer`, `_burn` or `_approve`
|
||||
should be removed in favor of using the `auth` argument in `_update` and `_approve`. This is showcased in `ERC721Burnable.burn` and in `ERC721Wrapper.withdrawTo`.
|
||||
In this logic of removing hidden SLOADs, the `_isApprovedOrOwner` function was removed in favor of a new `_isAuthorized` function. Overrides that used to target the `_isApprovedOrOwner` should now be performed on the `_isAuthorized` function. Calls to `_isApprovedOrOwner` that preceded a call to `_transfer`, `_burn` or `_approve` should be removed in favor of using the `auth` argument in `_update` and `_approve`. This is showcased in `ERC721Burnable.burn` and in `ERC721Wrapper.withdrawTo`.
|
||||
|
||||
The `_exists` function was removed. Calls to this function can be replaced by `_ownerOf(tokenId) != address(0)`.
|
||||
|
||||
#### More about ERC1155
|
||||
|
||||
Batch transfers will now emit `TransferSingle` if the batch consists of a single token, while in previous versions the `TransferBatch` event would be used for all transfers initiated through `safeBatchTransferFrom`. Both behaviors are compliant with the ERC-1155 specification.
|
||||
|
||||
#### ERC165Storage
|
||||
|
||||
Users that were registering EIP-165 interfaces with `_registerInterface` from `ERC165Storage` should instead do so so by overriding the `supportsInterface` function as seen below:
|
||||
|
||||
```solidity
|
||||
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
|
||||
return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
|
||||
return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
|
||||
}
|
||||
```
|
||||
|
||||
#### SafeMath
|
||||
|
||||
Methods in SafeMath superseded by native overflow checks in Solidity 0.8.0 were removed along with operations providing an interface for revert strings. The remaining methods were moved to `utils/Math.sol`.
|
||||
|
||||
```diff
|
||||
- import "@openzeppelin/contracts/utils/math/SafeMath.sol";
|
||||
+ import "@openzeppelin/contracts/utils/math/Math.sol";
|
||||
|
||||
function tryOperations(uint256 x, uint256 y) external view {
|
||||
- (bool overflowsAdd, uint256 resultAdd) = SafeMath.tryAdd(x, y);
|
||||
+ (bool overflowsAdd, uint256 resultAdd) = Math.tryAdd(x, y);
|
||||
- (bool overflowsSub, uint256 resultSub) = SafeMath.trySub(x, y);
|
||||
+ (bool overflowsSub, uint256 resultSub) = Math.trySub(x, y);
|
||||
- (bool overflowsMul, uint256 resultMul) = SafeMath.tryMul(x, y);
|
||||
+ (bool overflowsMul, uint256 resultMul) = Math.tryMul(x, y);
|
||||
- (bool overflowsDiv, uint256 resultDiv) = SafeMath.tryDiv(x, y);
|
||||
+ (bool overflowsDiv, uint256 resultDiv) = Math.tryDiv(x, y);
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### Adapting Governor modules
|
||||
|
||||
Custom Governor modules that override internal functions may require modifications if migrated to v5. In particular, the new internal functions `_queueOperations` and `_executeOperations` may need to be used. If assistance with this migration is needed reach out via the [OpenZeppelin Support Forum](https://forum.openzeppelin.com/c/support/contracts/18).
|
||||
|
||||
#### ECDSA and MessageHashUtils
|
||||
|
||||
The `ECDSA` library is now focused on signer recovery. Previously it also included utility methods for producing digests to be used with signing or recovery. These utilities have been moved to the `MessageHashUtils` library and should be imported if needed:
|
||||
|
||||
```diff
|
||||
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
|
||||
+import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
|
||||
|
||||
contract Verifier {
|
||||
using ECDSA for bytes32;
|
||||
+ using MessageHashUtils for bytes32;
|
||||
|
||||
function _verify(bytes32 data, bytes memory signature, address account) internal pure returns (bool) {
|
||||
return data
|
||||
.toEthSignedMessageHash()
|
||||
.recover(signature) == account;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Interfaces and libraries in upgradeable contracts
|
||||
|
||||
The upgradeable version of the contracts library used to include a variant suffixed with `Upgradeable` for every contract. These variants, which are produced automatically, mainly include changes for dealing with storage that don't apply to libraries and interfaces.
|
||||
|
||||
The upgradeable library no longer includes upgradeable variants for libraries and interfaces. Projects migrating to 5.0 should replace their library and interface imports with their corresponding non-upgradeable version:
|
||||
|
||||
```diff
|
||||
// Libraries
|
||||
-import {AddressUpgradeable} from '@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol';
|
||||
+import {Address} from '@openzeppelin/contracts/utils/Address.sol';
|
||||
|
||||
// Interfaces
|
||||
-import {IERC20Upgradeable} from '@openzeppelin/contracts-upgradeable/interfaces/IERC20.sol';
|
||||
+import {IERC20} from '@openzeppelin/contracts/interfaces/IERC20.sol';
|
||||
```
|
||||
|
||||
#### Offchain Considerations
|
||||
|
||||
Some changes may affect offchain systems if they rely on assumptions that are changed along with these new breaking changes. These cases are:
|
||||
|
||||
##### Relying on revert strings for processing errors
|
||||
|
||||
A concrete example is AccessControl, where it was previously advised to catch revert reasons using the following regex:
|
||||
|
||||
```
|
||||
/^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
|
||||
```
|
||||
|
||||
Instead, contracts now revert with custom errors. Systems that interact with smart contracts outside of the network should consider reliance on revert strings and possibly support the new custom errors.
|
||||
|
||||
##### Relying on storage locations for retrieving data
|
||||
|
||||
After 5.0, the storage location of some variables were changed. This is the case for `Initializable` and all the upgradeable contracts since they now use namespaced storaged locations. Any system relying on storage locations for retrieving data or detecting capabilities should be updated to support these new locations.
|
||||
|
||||
## 4.9.2 (2023-06-16)
|
||||
|
||||
- `MerkleProof`: Fix a bug in `processMultiProof` and `processMultiProofCalldata` that allows proving arbitrary leaves if the tree contains a node with value 0 at depth 1.
|
||||
|
||||
16
README.md
16
README.md
@ -1,6 +1,3 @@
|
||||
> **Warning**
|
||||
> Version 5.0 is under active development. The code in this branch is not recommended for use.
|
||||
|
||||
# <img src="logo.svg" alt="OpenZeppelin" height="40px">
|
||||
|
||||
[](https://www.npmjs.org/package/@openzeppelin/contracts)
|
||||
@ -17,7 +14,10 @@
|
||||
|
||||
:mage: **Not sure how to get started?** Check out [Contracts Wizard](https://wizard.openzeppelin.com/) — an interactive smart contract generator.
|
||||
|
||||
:building_construction: **Want to scale your decentralized application?** Check out [OpenZeppelin Defender](https://openzeppelin.com/defender) — a secure platform for automating and monitoring your operations.
|
||||
:building_construction: **Want to scale your decentralized application?** Check out [OpenZeppelin Defender](https://openzeppelin.com/defender) — a mission-critical developer security platform to code, audit, deploy, monitor, and operate with confidence.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> OpenZeppelin Contracts uses semantic versioning to communicate backwards compatibility of its API and storage layout. For upgradeable contracts, the storage layout of different major versions should be assumed incompatible, for example, it is unsafe to upgrade from 4.9.3 to 5.0.0. Learn more at [Backwards Compatibility](https://docs.openzeppelin.com/contracts/backwards-compatibility).
|
||||
|
||||
## Overview
|
||||
|
||||
@ -29,13 +29,13 @@
|
||||
$ npm install @openzeppelin/contracts
|
||||
```
|
||||
|
||||
OpenZeppelin Contracts features a [stable API](https://docs.openzeppelin.com/contracts/releases-stability#api-stability), which means that your contracts won't break unexpectedly when upgrading to a newer minor version.
|
||||
|
||||
#### Foundry (git)
|
||||
|
||||
> **Warning** When installing via git, it is a common error to use the `master` branch. This is a development branch that should be avoided in favor of tagged releases. The release process involves security measures that the `master` branch does not guarantee.
|
||||
> [!WARNING]
|
||||
> When installing via git, it is a common error to use the `master` branch. This is a development branch that should be avoided in favor of tagged releases. The release process involves security measures that the `master` branch does not guarantee.
|
||||
|
||||
> **Warning** Foundry installs the latest version initially, but subsequent `forge update` commands will use the `master` branch.
|
||||
> [!WARNING]
|
||||
> Foundry installs the latest version initially, but subsequent `forge update` commands will use the `master` branch.
|
||||
|
||||
```
|
||||
$ forge install OpenZeppelin/openzeppelin-contracts
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
# Releasing
|
||||
|
||||
> Visit the documentation for [details about release schedule](https://docs.openzeppelin.com/contracts/releases-stability).
|
||||
|
||||
OpenZeppelin Contracts uses a fully automated release process that takes care of compiling, packaging, and publishing the library, all of which is carried out in a clean CI environment (GitHub Actions), implemented in the ([`release-cycle`](.github/workflows/release-cycle.yml)) workflow. This helps to reduce the potential for human error and inconsistencies, and ensures that the release process is ongoing and reliable.
|
||||
|
||||
## Changesets
|
||||
|
||||
@ -39,4 +39,4 @@ Note as well that the Solidity language itself only guarantees security updates
|
||||
|
||||
## Legal
|
||||
|
||||
Smart contracts are a nascent techology and carry a high level of technical risk and uncertainty. OpenZeppelin Contracts is made available under the MIT License, which disclaims all warranties in relation to the project and which limits the liability of those that contribute and maintain the project, including OpenZeppelin. Your use of the project is also governed by the terms found at www.openzeppelin.com/tos (the "Terms"). As set out in the Terms, you are solely responsible for any use of OpenZeppelin Contracts and you assume all risks associated with any such use. This Security Policy in no way evidences or represents an on-going duty by any contributor, including OpenZeppelin, to correct any flaws or alert you to all or any of the potential risks of utilizing the project.
|
||||
Smart contracts are a nascent technology and carry a high level of technical risk and uncertainty. OpenZeppelin Contracts is made available under the MIT License, which disclaims all warranties in relation to the project and which limits the liability of those that contribute and maintain the project, including OpenZeppelin. Your use of the project is also governed by the terms found at www.openzeppelin.com/tos (the "Terms"). As set out in the Terms, you are solely responsible for any use of OpenZeppelin Contracts and you assume all risks associated with any such use. This Security Policy in no way evidences or represents an on-going duty by any contributor, including OpenZeppelin, to correct any flaws or alert you to all or any of the potential risks of utilizing the project.
|
||||
|
||||
BIN
audits/2023-10-v5.0.pdf
Normal file
BIN
audits/2023-10-v5.0.pdf
Normal file
Binary file not shown.
@ -2,6 +2,7 @@
|
||||
|
||||
| Date | Version | Commit | Auditor | Scope | Links |
|
||||
| ------------ | ------- | --------- | ------------ | -------------------- | ----------------------------------------------------------- |
|
||||
| October 2023 | v5.0.0 | `b5a3e69` | OpenZeppelin | v5.0 Changes | [🔗](./2023-10-v5.0.pdf) |
|
||||
| May 2023 | v4.9.0 | `91df66c` | OpenZeppelin | v4.9 Changes | [🔗](./2023-05-v4.9.pdf) |
|
||||
| October 2022 | v4.8.0 | `14f98db` | OpenZeppelin | ERC4626, Checkpoints | [🔗](./2022-10-ERC4626.pdf) [🔗](./2022-10-Checkpoints.pdf) |
|
||||
| October 2018 | v2.0.0 | `dac5bcc` | LevelK | Everything | [🔗](./2018-10.pdf) |
|
||||
|
||||
97
certora/diff/access_manager_AccessManager.sol.patch
Normal file
97
certora/diff/access_manager_AccessManager.sol.patch
Normal file
@ -0,0 +1,97 @@
|
||||
--- access/manager/AccessManager.sol 2023-10-05 12:17:09.694051809 -0300
|
||||
+++ access/manager/AccessManager.sol 2023-10-05 12:26:18.498688718 -0300
|
||||
@@ -6,7 +6,6 @@
|
||||
import {IAccessManaged} from "./IAccessManaged.sol";
|
||||
import {Address} from "../../utils/Address.sol";
|
||||
import {Context} from "../../utils/Context.sol";
|
||||
-import {Multicall} from "../../utils/Multicall.sol";
|
||||
import {Math} from "../../utils/math/Math.sol";
|
||||
import {Time} from "../../utils/types/Time.sol";
|
||||
|
||||
@@ -57,7 +56,8 @@
|
||||
* mindful of the danger associated with functions such as {{Ownable-renounceOwnership}} or
|
||||
* {{AccessControl-renounceRole}}.
|
||||
*/
|
||||
-contract AccessManager is Context, Multicall, IAccessManager {
|
||||
+// NOTE: The FV version of this contract doesn't include Multicall because CVL HAVOCs on any `delegatecall`.
|
||||
+contract AccessManager is Context, IAccessManager {
|
||||
using Time for *;
|
||||
|
||||
// Structure that stores the details for a target contract.
|
||||
@@ -105,7 +105,7 @@
|
||||
|
||||
// Used to identify operations that are currently being executed via {execute}.
|
||||
// This should be transient storage when supported by the EVM.
|
||||
- bytes32 private _executionId;
|
||||
+ bytes32 internal _executionId; // private → internal for FV
|
||||
|
||||
/**
|
||||
* @dev Check that the caller is authorized to perform the operation, following the restrictions encoded in
|
||||
@@ -253,6 +253,11 @@
|
||||
_setGrantDelay(roleId, newDelay);
|
||||
}
|
||||
|
||||
+ // Exposed for FV
|
||||
+ function _getTargetAdminDelayFull(address target) internal view virtual returns (uint32, uint32, uint48) {
|
||||
+ return _targets[target].adminDelay.getFull();
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* @dev Internal version of {grantRole} without access control. Returns true if the role was newly granted.
|
||||
*
|
||||
@@ -287,6 +292,11 @@
|
||||
return newMember;
|
||||
}
|
||||
|
||||
+ // Exposed for FV
|
||||
+ function _getRoleGrantDelayFull(uint64 roleId) internal view virtual returns (uint32, uint32, uint48) {
|
||||
+ return _roles[roleId].grantDelay.getFull();
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* @dev Internal version of {revokeRole} without access control. This logic is also used by {renounceRole}.
|
||||
* Returns true if the role was previously granted.
|
||||
@@ -586,7 +596,7 @@
|
||||
/**
|
||||
* @dev Check if the current call is authorized according to admin logic.
|
||||
*/
|
||||
- function _checkAuthorized() private {
|
||||
+ function _checkAuthorized() internal virtual { // private → internal virtual for FV
|
||||
address caller = _msgSender();
|
||||
(bool immediate, uint32 delay) = _canCallSelf(caller, _msgData());
|
||||
if (!immediate) {
|
||||
@@ -609,7 +619,7 @@
|
||||
*/
|
||||
function _getAdminRestrictions(
|
||||
bytes calldata data
|
||||
- ) private view returns (bool restricted, uint64 roleAdminId, uint32 executionDelay) {
|
||||
+ ) internal view returns (bool restricted, uint64 roleAdminId, uint32 executionDelay) { // private → internal for FV
|
||||
if (data.length < 4) {
|
||||
return (false, 0, 0);
|
||||
}
|
||||
@@ -662,7 +672,7 @@
|
||||
address caller,
|
||||
address target,
|
||||
bytes calldata data
|
||||
- ) private view returns (bool immediate, uint32 delay) {
|
||||
+ ) internal view returns (bool immediate, uint32 delay) { // private → internal for FV
|
||||
if (target == address(this)) {
|
||||
return _canCallSelf(caller, data);
|
||||
} else {
|
||||
@@ -716,14 +726,14 @@
|
||||
/**
|
||||
* @dev Extracts the selector from calldata. Panics if data is not at least 4 bytes
|
||||
*/
|
||||
- function _checkSelector(bytes calldata data) private pure returns (bytes4) {
|
||||
+ function _checkSelector(bytes calldata data) internal pure returns (bytes4) { // private → internal for FV
|
||||
return bytes4(data[0:4]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Hashing function for execute protection
|
||||
*/
|
||||
- function _hashExecutionId(address target, bytes4 selector) private pure returns (bytes32) {
|
||||
+ function _hashExecutionId(address target, bytes4 selector) internal pure returns (bytes32) { // private → internal for FV
|
||||
return keccak256(abi.encode(target, selector));
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)
|
||||
// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)
|
||||
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
|
||||
// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)
|
||||
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
|
||||
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
|
||||
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)
|
||||
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol)
|
||||
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
|
||||
@ -5,7 +5,9 @@ NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/
|
||||
|
||||
This directory provides ways to restrict who can access the functions of a contract or when they can do it.
|
||||
|
||||
- {AccessControl} provides a general role based access control mechanism. Multiple hierarchical roles can be created and assigned each to multiple accounts.
|
||||
- {AccessManager} is a full-fledged access control solution for smart contract systems. Allows creating and assigning multiple hierarchical roles with execution delays for each account across various contracts.
|
||||
- {AccessManaged} delegates its access control to an authority that dictates the permissions of the managed contract. It's compatible with an AccessManager as an authority.
|
||||
- {AccessControl} provides a per-contract role based access control mechanism. Multiple hierarchical roles can be created and assigned each to multiple accounts within the same instance.
|
||||
- {Ownable} is a simpler mechanism with a single owner "role" that can be assigned to a single account. This simpler mechanism can be useful for quick tests but projects with production concerns are likely to outgrow it.
|
||||
|
||||
== Core
|
||||
@ -32,8 +34,12 @@ This directory provides ways to restrict who can access the functions of a contr
|
||||
|
||||
{{IAuthority}}
|
||||
|
||||
{{IAccessManager}}
|
||||
|
||||
{{AccessManager}}
|
||||
|
||||
{{IAccessManaged}}
|
||||
|
||||
{{AccessManaged}}
|
||||
|
||||
{{AccessManagerAdapter}}
|
||||
{{AuthorityUtils}}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControlDefaultAdminRules.sol)
|
||||
// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlDefaultAdminRules.sol)
|
||||
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)
|
||||
// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)
|
||||
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.9.0) (access/IAccessControlDefaultAdminRules.sol)
|
||||
// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlDefaultAdminRules.sol)
|
||||
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)
|
||||
// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)
|
||||
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v5.0.0) (access/manager/AccessManaged.sol)
|
||||
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
@ -41,17 +42,15 @@ abstract contract AccessManaged is Context, IAccessManaged {
|
||||
* function at the bottom of the call stack, and not the function where the modifier is visible in the source code.
|
||||
* ====
|
||||
*
|
||||
* [NOTE]
|
||||
* [WARNING]
|
||||
* ====
|
||||
* Selector collisions are mitigated by scoping permissions per contract, but some edge cases must be considered:
|
||||
* Avoid adding this modifier to the https://docs.soliditylang.org/en/v0.8.20/contracts.html#receive-ether-function[`receive()`]
|
||||
* function or the https://docs.soliditylang.org/en/v0.8.20/contracts.html#fallback-function[`fallback()`]. These
|
||||
* functions are the only execution paths where a function selector cannot be unambiguosly determined from the calldata
|
||||
* since the selector defaults to `0x00000000` in the `receive()` function and similarly in the `fallback()` function
|
||||
* if no calldata is provided. (See {_checkCanCall}).
|
||||
*
|
||||
* * If the https://docs.soliditylang.org/en/v0.8.20/contracts.html#receive-ether-function[`receive()`] function
|
||||
* is restricted, any other function with a `0x00000000` selector will share permissions with `receive()`.
|
||||
* * Similarly, if there's no `receive()` function but a `fallback()` instead, the fallback might be called with
|
||||
* empty `calldata`, sharing the `0x00000000` selector permissions as well.
|
||||
* * For any other selector, if the restricted function is set on an upgradeable contract, an upgrade may remove
|
||||
* the restricted function and replace it with a new method whose selector replaces the last one, keeping the
|
||||
* previous permissions.
|
||||
* The `receive()` function will always panic whereas the `fallback()` may panic depending on the calldata length.
|
||||
* ====
|
||||
*/
|
||||
modifier restricted() {
|
||||
@ -59,16 +58,12 @@ abstract contract AccessManaged is Context, IAccessManaged {
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the current authority.
|
||||
*/
|
||||
/// @inheritdoc IAccessManaged
|
||||
function authority() public view virtual returns (address) {
|
||||
return _authority;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Transfers control to a new authority. The caller must be the current authority.
|
||||
*/
|
||||
/// @inheritdoc IAccessManaged
|
||||
function setAuthority(address newAuthority) public virtual {
|
||||
address caller = _msgSender();
|
||||
if (caller != authority()) {
|
||||
@ -80,11 +75,7 @@ abstract contract AccessManaged is Context, IAccessManaged {
|
||||
_setAuthority(newAuthority);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns true only in the context of a delayed restricted call, at the moment that the scheduled operation is
|
||||
* being consumed. Prevents denial of service for delayed restricted calls in the case that the contract performs
|
||||
* attacker controlled calls.
|
||||
*/
|
||||
/// @inheritdoc IAccessManaged
|
||||
function isConsumingScheduledOp() public view returns (bytes4) {
|
||||
return _consumingSchedule ? this.isConsumingScheduledOp.selector : bytes4(0);
|
||||
}
|
||||
@ -99,14 +90,15 @@ abstract contract AccessManaged is Context, IAccessManaged {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Reverts if the caller is not allowed to call the function identified by a selector.
|
||||
* @dev Reverts if the caller is not allowed to call the function identified by a selector. Panics if the calldata
|
||||
* is less than 4 bytes long.
|
||||
*/
|
||||
function _checkCanCall(address caller, bytes calldata data) internal virtual {
|
||||
(bool immediate, uint32 delay) = AuthorityUtils.canCallWithDelay(
|
||||
authority(),
|
||||
caller,
|
||||
address(this),
|
||||
bytes4(data)
|
||||
bytes4(data[0:4])
|
||||
);
|
||||
if (!immediate) {
|
||||
if (delay > 0) {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v5.0.0) (access/manager/AccessManager.sol)
|
||||
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
@ -13,23 +14,32 @@ import {Time} from "../../utils/types/Time.sol";
|
||||
/**
|
||||
* @dev AccessManager is a central contract to store the permissions of a system.
|
||||
*
|
||||
* The smart contracts under the control of an AccessManager instance will have a set of "restricted" functions, and the
|
||||
* exact details of how access is restricted for each of those functions is configurable by the admins of the instance.
|
||||
* These restrictions are expressed in terms of "roles".
|
||||
* A smart contract under the control of an AccessManager instance is known as a target, and will inherit from the
|
||||
* {AccessManaged} contract, be connected to this contract as its manager and implement the {AccessManaged-restricted}
|
||||
* modifier on a set of functions selected to be permissioned. Note that any function without this setup won't be
|
||||
* effectively restricted.
|
||||
*
|
||||
* An AccessManager instance will define a set of roles. Accounts can be added into any number of these roles. Each of
|
||||
* them defines a role, and may confer access to some of the restricted functions in the system, as configured by admins
|
||||
* through the use of {setFunctionAllowedRoles}.
|
||||
* The restriction rules for such functions are defined in terms of "roles" identified by an `uint64` and scoped
|
||||
* by target (`address`) and function selectors (`bytes4`). These roles are stored in this contract and can be
|
||||
* configured by admins (`ADMIN_ROLE` members) after a delay (see {getTargetAdminDelay}).
|
||||
*
|
||||
* Note that a function in a target contract may become permissioned in this way only when: 1) said contract is
|
||||
* {AccessManaged} and is connected to this contract as its manager, and 2) said function is decorated with the
|
||||
* `restricted` modifier.
|
||||
* For each target contract, admins can configure the following without any delay:
|
||||
*
|
||||
* There is a special role defined by default named "public" which all accounts automatically have.
|
||||
* * The target's {AccessManaged-authority} via {updateAuthority}.
|
||||
* * Close or open a target via {setTargetClosed} keeping the permissions intact.
|
||||
* * The roles that are allowed (or disallowed) to call a given function (identified by its selector) through {setTargetFunctionRole}.
|
||||
*
|
||||
* In addition to the access rules defined by each target's functions being assigned to roles, then entire target can
|
||||
* be "closed". This "closed" mode is set/unset by the admin using {setTargetClosed} and can be used to lock a contract
|
||||
* while permissions are being (re-)configured.
|
||||
* By default every address is member of the `PUBLIC_ROLE` and every target function is restricted to the `ADMIN_ROLE` until configured otherwise.
|
||||
* Additionally, each role has the following configuration options restricted to this manager's admins:
|
||||
*
|
||||
* * A role's admin role via {setRoleAdmin} who can grant or revoke roles.
|
||||
* * A role's guardian role via {setRoleGuardian} who's allowed to cancel operations.
|
||||
* * A delay in which a role takes effect after being granted through {setGrantDelay}.
|
||||
* * A delay of any target's admin action via {setTargetAdminDelay}.
|
||||
* * A role label for discoverability purposes with {labelRole}.
|
||||
*
|
||||
* Any account can be added and removed into any number of these roles by using the {grantRole} and {revokeRole} functions
|
||||
* restricted to each role's admin (see {getRoleAdmin}).
|
||||
*
|
||||
* Since all the permissions of the managed system can be modified by the admins of this instance, it is expected that
|
||||
* they will be highly secured (e.g., a multisig or a well-configured DAO).
|
||||
@ -60,28 +70,30 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
|
||||
// Structure that stores the details for a role/account pair. This structures fit into a single slot.
|
||||
struct Access {
|
||||
// Timepoint at which the user gets the permission. If this is either 0, or in the future, the role
|
||||
// permission is not available.
|
||||
// Timepoint at which the user gets the permission.
|
||||
// If this is either 0 or in the future, then the role permission is not available.
|
||||
uint48 since;
|
||||
// Delay for execution. Only applies to restricted() / execute() calls.
|
||||
Time.Delay delay;
|
||||
}
|
||||
|
||||
// Structure that stores the details of a role, including:
|
||||
// - the members of the role
|
||||
// - the admin role (that can grant or revoke permissions)
|
||||
// - the guardian role (that can cancel operations targeting functions that need this role)
|
||||
// - the grand delay
|
||||
// Structure that stores the details of a role.
|
||||
struct Role {
|
||||
// Members of the role.
|
||||
mapping(address user => Access access) members;
|
||||
// Admin who can grant or revoke permissions.
|
||||
uint64 admin;
|
||||
// Guardian who can cancel operations targeting functions that need this role.
|
||||
uint64 guardian;
|
||||
// Delay in which the role takes effect after being granted.
|
||||
Time.Delay grantDelay;
|
||||
}
|
||||
|
||||
// Structure that stores the details for a scheduled operation. This structure fits into a single slot.
|
||||
struct Schedule {
|
||||
// Moment at which the operation can be executed.
|
||||
uint48 timepoint;
|
||||
// Operation nonce to allow third-party contracts to identify the operation.
|
||||
uint32 nonce;
|
||||
}
|
||||
|
||||
@ -92,6 +104,7 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
mapping(uint64 roleId => Role) private _roles;
|
||||
mapping(bytes32 operationId => Schedule) private _schedules;
|
||||
|
||||
// Used to identify operations that are currently being executed via {execute}.
|
||||
// This should be transient storage when supported by the EVM.
|
||||
bytes32 private _executionId;
|
||||
|
||||
@ -114,23 +127,12 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
}
|
||||
|
||||
// =================================================== GETTERS ====================================================
|
||||
/**
|
||||
* @dev Check if an address (`caller`) is authorised to call a given function on a given contract directly (with
|
||||
* no restriction). Additionally, it returns the delay needed to perform the call indirectly through the {schedule}
|
||||
* & {execute} workflow.
|
||||
*
|
||||
* This function is usually called by the targeted contract to control immediate execution of restricted functions.
|
||||
* Therefore we only return true is the call can be performed without any delay. If the call is subject to a delay,
|
||||
* then the function should return false, and the caller should schedule the operation for future execution.
|
||||
*
|
||||
* We may be able to hash the operation, and check if the call was scheduled, but we would not be able to cleanup
|
||||
* the schedule, leaving the possibility of multiple executions. Maybe this function should not be view?
|
||||
*
|
||||
* NOTE: The IAuthority interface does not include the `uint32` delay. This is an extension of that interface that
|
||||
* is backward compatible. Some contracts may thus ignore the second return argument. In that case they will fail
|
||||
* to identify the indirect workflow, and will consider calls that require a delay to be forbidden.
|
||||
*/
|
||||
function canCall(address caller, address target, bytes4 selector) public view virtual returns (bool, uint32) {
|
||||
/// @inheritdoc IAccessManager
|
||||
function canCall(
|
||||
address caller,
|
||||
address target,
|
||||
bytes4 selector
|
||||
) public view virtual returns (bool immediate, uint32 delay) {
|
||||
if (isTargetClosed(target)) {
|
||||
return (false, 0);
|
||||
} else if (caller == address(this)) {
|
||||
@ -144,96 +146,64 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Expiration delay for scheduled proposals. Defaults to 1 week.
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function expiration() public view virtual returns (uint32) {
|
||||
return 1 weeks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Minimum setback for all delay updates, with the exception of execution delays, which
|
||||
* can be increased without setback (and in the event of an accidental increase can be reset
|
||||
* via {revokeRole}). Defaults to 5 days.
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function minSetback() public view virtual returns (uint32) {
|
||||
return 5 days;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get the mode under which a contract is operating.
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function isTargetClosed(address target) public view virtual returns (bool) {
|
||||
return _targets[target].closed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get the role required to call a function.
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function getTargetFunctionRole(address target, bytes4 selector) public view virtual returns (uint64) {
|
||||
return _targets[target].allowedRoles[selector];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get the admin delay for a target contract. Changes to contract configuration are subject to this delay.
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function getTargetAdminDelay(address target) public view virtual returns (uint32) {
|
||||
return _targets[target].adminDelay.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get the id of the role that acts as an admin for given role.
|
||||
*
|
||||
* The admin permission is required to grant the role, revoke the role and update the execution delay to execute
|
||||
* an operation that is restricted to this role.
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function getRoleAdmin(uint64 roleId) public view virtual returns (uint64) {
|
||||
return _roles[roleId].admin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get the role that acts as a guardian for a given role.
|
||||
*
|
||||
* The guardian permission allows canceling operations that have been scheduled under the role.
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function getRoleGuardian(uint64 roleId) public view virtual returns (uint64) {
|
||||
return _roles[roleId].guardian;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get the role current grant delay, that value may change at any point, without an event emitted, following
|
||||
* a call to {setGrantDelay}. Changes to this value, including effect timepoint are notified by the
|
||||
* {RoleGrantDelayChanged} event.
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function getRoleGrantDelay(uint64 roleId) public view virtual returns (uint32) {
|
||||
return _roles[roleId].grantDelay.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get the access details for a given account for a given role. These details include the timepoint at which
|
||||
* membership becomes active, and the delay applied to all operation by this user that requires this permission
|
||||
* level.
|
||||
*
|
||||
* Returns:
|
||||
* [0] Timestamp at which the account membership becomes valid. 0 means role is not granted.
|
||||
* [1] Current execution delay for the account.
|
||||
* [2] Pending execution delay for the account.
|
||||
* [3] Timestamp at which the pending execution delay will become active. 0 means no delay update is scheduled.
|
||||
*/
|
||||
function getAccess(uint64 roleId, address account) public view virtual returns (uint48, uint32, uint32, uint48) {
|
||||
/// @inheritdoc IAccessManager
|
||||
function getAccess(
|
||||
uint64 roleId,
|
||||
address account
|
||||
) public view virtual returns (uint48 since, uint32 currentDelay, uint32 pendingDelay, uint48 effect) {
|
||||
Access storage access = _roles[roleId].members[account];
|
||||
|
||||
uint48 since = access.since;
|
||||
(uint32 currentDelay, uint32 pendingDelay, uint48 effect) = access.delay.getFull();
|
||||
since = access.since;
|
||||
(currentDelay, pendingDelay, effect) = access.delay.getFull();
|
||||
|
||||
return (since, currentDelay, pendingDelay, effect);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Check if a given account currently had the permission level corresponding to a given role. Note that this
|
||||
* permission might be associated with a delay. {getAccess} can provide more details.
|
||||
*/
|
||||
function hasRole(uint64 roleId, address account) public view virtual returns (bool, uint32) {
|
||||
/// @inheritdoc IAccessManager
|
||||
function hasRole(
|
||||
uint64 roleId,
|
||||
address account
|
||||
) public view virtual returns (bool isMember, uint32 executionDelay) {
|
||||
if (roleId == PUBLIC_ROLE) {
|
||||
return (true, 0);
|
||||
} else {
|
||||
@ -243,11 +213,7 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
}
|
||||
|
||||
// =============================================== ROLE MANAGEMENT ===============================================
|
||||
/**
|
||||
* @dev Give a label to a role, for improved role discoverabily by UIs.
|
||||
*
|
||||
* Emits a {RoleLabel} event.
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function labelRole(uint64 roleId, string calldata label) public virtual onlyAuthorized {
|
||||
if (roleId == ADMIN_ROLE || roleId == PUBLIC_ROLE) {
|
||||
revert AccessManagerLockedRole(roleId);
|
||||
@ -255,53 +221,17 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
emit RoleLabel(roleId, label);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Add `account` to `roleId`, or change its execution delay.
|
||||
*
|
||||
* This gives the account the authorization to call any function that is restricted to this role. An optional
|
||||
* execution delay (in seconds) can be set. If that delay is non 0, the user is required to schedule any operation
|
||||
* that is restricted to members this role. The user will only be able to execute the operation after the delay has
|
||||
* passed, before it has expired. During this period, admin and guardians can cancel the operation (see {cancel}).
|
||||
*
|
||||
* If the account has already been granted this role, the execution delay will be updated. This update is not
|
||||
* immediate and follows the delay rules. For example, If a user currently has a delay of 3 hours, and this is
|
||||
* called to reduce that delay to 1 hour, the new delay will take some time to take effect, enforcing that any
|
||||
* operation executed in the 3 hours that follows this update was indeed scheduled before this update.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must be an admin for the role (see {getRoleAdmin})
|
||||
*
|
||||
* Emits a {RoleGranted} event
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function grantRole(uint64 roleId, address account, uint32 executionDelay) public virtual onlyAuthorized {
|
||||
_grantRole(roleId, account, getRoleGrantDelay(roleId), executionDelay);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Remove an account from a role, with immediate effect. If the account does not have the role, this call has
|
||||
* no effect.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must be an admin for the role (see {getRoleAdmin})
|
||||
*
|
||||
* Emits a {RoleRevoked} event if the account had the role.
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function revokeRole(uint64 roleId, address account) public virtual onlyAuthorized {
|
||||
_revokeRole(roleId, account);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Renounce role permissions for the calling account, with immediate effect. If the sender is not in
|
||||
* the role, this call has no effect.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must be `callerConfirmation`.
|
||||
*
|
||||
* Emits a {RoleRevoked} event if the account had the role.
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function renounceRole(uint64 roleId, address callerConfirmation) public virtual {
|
||||
if (callerConfirmation != _msgSender()) {
|
||||
revert AccessManagerBadConfirmation();
|
||||
@ -309,41 +239,17 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
_revokeRole(roleId, callerConfirmation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Change admin role for a given role.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must be a global admin
|
||||
*
|
||||
* Emits a {RoleAdminChanged} event
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function setRoleAdmin(uint64 roleId, uint64 admin) public virtual onlyAuthorized {
|
||||
_setRoleAdmin(roleId, admin);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Change guardian role for a given role.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must be a global admin
|
||||
*
|
||||
* Emits a {RoleGuardianChanged} event
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function setRoleGuardian(uint64 roleId, uint64 guardian) public virtual onlyAuthorized {
|
||||
_setRoleGuardian(roleId, guardian);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Update the delay for granting a `roleId`.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must be a global admin
|
||||
*
|
||||
* Emits a {RoleGrantDelayChanged} event.
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function setGrantDelay(uint64 roleId, uint32 newDelay) public virtual onlyAuthorized {
|
||||
_setGrantDelay(roleId, newDelay);
|
||||
}
|
||||
@ -406,7 +312,10 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
/**
|
||||
* @dev Internal version of {setRoleAdmin} without access control.
|
||||
*
|
||||
* Emits a {RoleAdminChanged} event
|
||||
* Emits a {RoleAdminChanged} event.
|
||||
*
|
||||
* NOTE: Setting the admin role as the `PUBLIC_ROLE` is allowed, but it will effectively allow
|
||||
* anyone to set grant or revoke such role.
|
||||
*/
|
||||
function _setRoleAdmin(uint64 roleId, uint64 admin) internal virtual {
|
||||
if (roleId == ADMIN_ROLE || roleId == PUBLIC_ROLE) {
|
||||
@ -421,7 +330,10 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
/**
|
||||
* @dev Internal version of {setRoleGuardian} without access control.
|
||||
*
|
||||
* Emits a {RoleGuardianChanged} event
|
||||
* Emits a {RoleGuardianChanged} event.
|
||||
*
|
||||
* NOTE: Setting the guardian role as the `PUBLIC_ROLE` is allowed, but it will effectively allow
|
||||
* anyone to cancel any scheduled operation for such role.
|
||||
*/
|
||||
function _setRoleGuardian(uint64 roleId, uint64 guardian) internal virtual {
|
||||
if (roleId == ADMIN_ROLE || roleId == PUBLIC_ROLE) {
|
||||
@ -436,7 +348,7 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
/**
|
||||
* @dev Internal version of {setGrantDelay} without access control.
|
||||
*
|
||||
* Emits a {RoleGrantDelayChanged} event
|
||||
* Emits a {RoleGrantDelayChanged} event.
|
||||
*/
|
||||
function _setGrantDelay(uint64 roleId, uint32 newDelay) internal virtual {
|
||||
if (roleId == PUBLIC_ROLE) {
|
||||
@ -450,15 +362,7 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
}
|
||||
|
||||
// ============================================= FUNCTION MANAGEMENT ==============================================
|
||||
/**
|
||||
* @dev Set the role required to call functions identified by the `selectors` in the `target` contract.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must be a global admin
|
||||
*
|
||||
* Emits a {TargetFunctionRoleUpdated} event per selector.
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function setTargetFunctionRole(
|
||||
address target,
|
||||
bytes4[] calldata selectors,
|
||||
@ -470,24 +374,16 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Internal version of {setFunctionAllowedRole} without access control.
|
||||
* @dev Internal version of {setTargetFunctionRole} without access control.
|
||||
*
|
||||
* Emits a {TargetFunctionRoleUpdated} event
|
||||
* Emits a {TargetFunctionRoleUpdated} event.
|
||||
*/
|
||||
function _setTargetFunctionRole(address target, bytes4 selector, uint64 roleId) internal virtual {
|
||||
_targets[target].allowedRoles[selector] = roleId;
|
||||
emit TargetFunctionRoleUpdated(target, selector, roleId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Set the delay for changing the configuration of a given target contract.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must be a global admin
|
||||
*
|
||||
* Emits a {TargetAdminDelayUpdated} event per selector
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function setTargetAdminDelay(address target, uint32 newDelay) public virtual onlyAuthorized {
|
||||
_setTargetAdminDelay(target, newDelay);
|
||||
}
|
||||
@ -495,7 +391,7 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
/**
|
||||
* @dev Internal version of {setTargetAdminDelay} without access control.
|
||||
*
|
||||
* Emits a {TargetAdminDelayUpdated} event
|
||||
* Emits a {TargetAdminDelayUpdated} event.
|
||||
*/
|
||||
function _setTargetAdminDelay(address target, uint32 newDelay) internal virtual {
|
||||
uint48 effect;
|
||||
@ -505,15 +401,7 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
}
|
||||
|
||||
// =============================================== MODE MANAGEMENT ================================================
|
||||
/**
|
||||
* @dev Set the closed flag for a contract.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must be a global admin
|
||||
*
|
||||
* Emits a {TargetClosed} event.
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function setTargetClosed(address target, bool closed) public virtual onlyAuthorized {
|
||||
_setTargetClosed(target, closed);
|
||||
}
|
||||
@ -532,38 +420,18 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
}
|
||||
|
||||
// ============================================== DELAYED OPERATIONS ==============================================
|
||||
/**
|
||||
* @dev Return the timepoint at which a scheduled operation will be ready for execution. This returns 0 if the
|
||||
* operation is not yet scheduled, has expired, was executed, or was canceled.
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function getSchedule(bytes32 id) public view virtual returns (uint48) {
|
||||
uint48 timepoint = _schedules[id].timepoint;
|
||||
return _isExpired(timepoint) ? 0 : timepoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Return the nonce for the latest scheduled operation with a given id. Returns 0 if the operation has never
|
||||
* been scheduled.
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function getNonce(bytes32 id) public view virtual returns (uint32) {
|
||||
return _schedules[id].nonce;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Schedule a delayed operation for future execution, and return the operation identifier. It is possible to
|
||||
* choose the timestamp at which the operation becomes executable as long as it satisfies the execution delays
|
||||
* required for the caller. The special value zero will automatically set the earliest possible time.
|
||||
*
|
||||
* Returns the `operationId` that was scheduled. Since this value is a hash of the parameters, it can reoccur when
|
||||
* the same parameters are used; if this is relevant, the returned `nonce` can be used to uniquely identify this
|
||||
* scheduled operation from other occurrences of the same `operationId` in invocations of {execute} and {cancel}.
|
||||
*
|
||||
* Emits a {OperationScheduled} event.
|
||||
*
|
||||
* NOTE: It is not possible to concurrently schedule more than one operation with the same `target` and `data`. If
|
||||
* this is necessary, a random byte can be appended to `data` to act as a salt that will be ignored by the target
|
||||
* contract if it is using standard Solidity ABI encoding.
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function schedule(
|
||||
address target,
|
||||
bytes calldata data,
|
||||
@ -572,13 +440,13 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
address caller = _msgSender();
|
||||
|
||||
// Fetch restrictions that apply to the caller on the targeted function
|
||||
(bool immediate, uint32 setback) = _canCallExtended(caller, target, data);
|
||||
(, uint32 setback) = _canCallExtended(caller, target, data);
|
||||
|
||||
uint48 minWhen = Time.timestamp() + setback;
|
||||
|
||||
// if call is not authorized, or if requested timing is too soon
|
||||
if ((!immediate && setback == 0) || (when > 0 && when < minWhen)) {
|
||||
revert AccessManagerUnauthorizedCall(caller, target, bytes4(data[0:4]));
|
||||
// if call with delay is not authorized, or if requested timing is too soon
|
||||
if (setback == 0 || (when > 0 && when < minWhen)) {
|
||||
revert AccessManagerUnauthorizedCall(caller, target, _checkSelector(data));
|
||||
}
|
||||
|
||||
// Reuse variable due to stack too deep
|
||||
@ -611,15 +479,7 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Execute a function that is delay restricted, provided it was properly scheduled beforehand, or the
|
||||
* execution delay is 0.
|
||||
*
|
||||
* Returns the nonce that identifies the previously scheduled operation that is executed, or 0 if the
|
||||
* operation wasn't previously scheduled (if the caller doesn't have an execution delay).
|
||||
*
|
||||
* Emits an {OperationExecuted} event only if the call was scheduled and delayed.
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
// Reentrancy is not an issue because permissions are checked on msg.sender. Additionally,
|
||||
// _consumeScheduledOp guarantees a scheduled operation is only executed once.
|
||||
// slither-disable-next-line reentrancy-no-eth
|
||||
@ -631,20 +491,21 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
|
||||
// If caller is not authorised, revert
|
||||
if (!immediate && setback == 0) {
|
||||
revert AccessManagerUnauthorizedCall(caller, target, bytes4(data));
|
||||
revert AccessManagerUnauthorizedCall(caller, target, _checkSelector(data));
|
||||
}
|
||||
|
||||
// If caller is authorised, check operation was scheduled early enough
|
||||
bytes32 operationId = hashOperation(caller, target, data);
|
||||
uint32 nonce;
|
||||
|
||||
if (setback != 0) {
|
||||
// If caller is authorised, check operation was scheduled early enough
|
||||
// Consume an available schedule even if there is no currently enforced delay
|
||||
if (setback != 0 || getSchedule(operationId) != 0) {
|
||||
nonce = _consumeScheduledOp(operationId);
|
||||
}
|
||||
|
||||
// Mark the target and selector as authorised
|
||||
bytes32 executionIdBefore = _executionId;
|
||||
_executionId = _hashExecutionId(target, bytes4(data));
|
||||
_executionId = _hashExecutionId(target, _checkSelector(data));
|
||||
|
||||
// Perform call
|
||||
Address.functionCallWithValue(target, data, msg.value);
|
||||
@ -655,15 +516,31 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
return nonce;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Consume a scheduled operation targeting the caller. If such an operation exists, mark it as consumed
|
||||
* (emit an {OperationExecuted} event and clean the state). Otherwise, throw an error.
|
||||
*
|
||||
* This is useful for contract that want to enforce that calls targeting them were scheduled on the manager,
|
||||
* with all the verifications that it implies.
|
||||
*
|
||||
* Emit a {OperationExecuted} event
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function cancel(address caller, address target, bytes calldata data) public virtual returns (uint32) {
|
||||
address msgsender = _msgSender();
|
||||
bytes4 selector = _checkSelector(data);
|
||||
|
||||
bytes32 operationId = hashOperation(caller, target, data);
|
||||
if (_schedules[operationId].timepoint == 0) {
|
||||
revert AccessManagerNotScheduled(operationId);
|
||||
} else if (caller != msgsender) {
|
||||
// calls can only be canceled by the account that scheduled them, a global admin, or by a guardian of the required role.
|
||||
(bool isAdmin, ) = hasRole(ADMIN_ROLE, msgsender);
|
||||
(bool isGuardian, ) = hasRole(getRoleGuardian(getTargetFunctionRole(target, selector)), msgsender);
|
||||
if (!isAdmin && !isGuardian) {
|
||||
revert AccessManagerUnauthorizedCancel(msgsender, caller, target, selector);
|
||||
}
|
||||
}
|
||||
|
||||
delete _schedules[operationId].timepoint; // reset the timepoint, keep the nonce
|
||||
uint32 nonce = _schedules[operationId].nonce;
|
||||
emit OperationCanceled(operationId, nonce);
|
||||
|
||||
return nonce;
|
||||
}
|
||||
|
||||
/// @inheritdoc IAccessManager
|
||||
function consumeScheduledOp(address caller, bytes calldata data) public virtual {
|
||||
address target = _msgSender();
|
||||
if (IAccessManaged(target).isConsumingScheduledOp() != IAccessManaged.isConsumingScheduledOp.selector) {
|
||||
@ -695,61 +572,13 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
return nonce;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Cancel a scheduled (delayed) operation. Returns the nonce that identifies the previously scheduled
|
||||
* operation that is cancelled.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must be the proposer, a guardian of the targeted function, or a global admin
|
||||
*
|
||||
* Emits a {OperationCanceled} event.
|
||||
*/
|
||||
function cancel(address caller, address target, bytes calldata data) public virtual returns (uint32) {
|
||||
address msgsender = _msgSender();
|
||||
bytes4 selector = bytes4(data[0:4]);
|
||||
|
||||
bytes32 operationId = hashOperation(caller, target, data);
|
||||
if (_schedules[operationId].timepoint == 0) {
|
||||
revert AccessManagerNotScheduled(operationId);
|
||||
} else if (caller != msgsender) {
|
||||
// calls can only be canceled by the account that scheduled them, a global admin, or by a guardian of the required role.
|
||||
(bool isAdmin, ) = hasRole(ADMIN_ROLE, msgsender);
|
||||
(bool isGuardian, ) = hasRole(getRoleGuardian(getTargetFunctionRole(target, selector)), msgsender);
|
||||
if (!isAdmin && !isGuardian) {
|
||||
revert AccessManagerUnauthorizedCancel(msgsender, caller, target, selector);
|
||||
}
|
||||
}
|
||||
|
||||
delete _schedules[operationId].timepoint; // reset the timepoint, keep the nonce
|
||||
uint32 nonce = _schedules[operationId].nonce;
|
||||
emit OperationCanceled(operationId, nonce);
|
||||
|
||||
return nonce;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Hashing function for delayed operations
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function hashOperation(address caller, address target, bytes calldata data) public view virtual returns (bytes32) {
|
||||
return keccak256(abi.encode(caller, target, data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Hashing function for execute protection
|
||||
*/
|
||||
function _hashExecutionId(address target, bytes4 selector) private pure returns (bytes32) {
|
||||
return keccak256(abi.encode(target, selector));
|
||||
}
|
||||
|
||||
// ==================================================== OTHERS ====================================================
|
||||
/**
|
||||
* @dev Change the AccessManager instance used by a contract that correctly uses this instance.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must be a global admin
|
||||
*/
|
||||
/// @inheritdoc IAccessManager
|
||||
function updateAuthority(address target, address newAuthority) public virtual onlyAuthorized {
|
||||
IAccessManaged(target).setAuthority(newAuthority);
|
||||
}
|
||||
@ -777,15 +606,17 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
* Returns:
|
||||
* - bool restricted: does this data match a restricted operation
|
||||
* - uint64: which role is this operation restricted to
|
||||
* - uint32: minimum delay to enforce for that operation (on top of the admin's execution delay)
|
||||
* - uint32: minimum delay to enforce for that operation (max between operation's delay and admin's execution delay)
|
||||
*/
|
||||
function _getAdminRestrictions(bytes calldata data) private view returns (bool, uint64, uint32) {
|
||||
bytes4 selector = bytes4(data);
|
||||
|
||||
function _getAdminRestrictions(
|
||||
bytes calldata data
|
||||
) private view returns (bool restricted, uint64 roleAdminId, uint32 executionDelay) {
|
||||
if (data.length < 4) {
|
||||
return (false, 0, 0);
|
||||
}
|
||||
|
||||
bytes4 selector = _checkSelector(data);
|
||||
|
||||
// Restricted to ADMIN with no delay beside any execution delay the caller may have
|
||||
if (
|
||||
selector == this.labelRole.selector ||
|
||||
@ -813,8 +644,7 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
if (selector == this.grantRole.selector || selector == this.revokeRole.selector) {
|
||||
// First argument is a roleId.
|
||||
uint64 roleId = abi.decode(data[0x04:0x24], (uint64));
|
||||
uint64 roleAdminId = getRoleAdmin(roleId);
|
||||
return (true, roleAdminId, 0);
|
||||
return (true, getRoleAdmin(roleId), 0);
|
||||
}
|
||||
|
||||
return (false, 0, 0);
|
||||
@ -822,21 +652,22 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
|
||||
// =================================================== HELPERS ====================================================
|
||||
/**
|
||||
* @dev An extended version of {canCall} for internal use that considers restrictions for admin functions.
|
||||
* @dev An extended version of {canCall} for internal usage that checks {_canCallSelf}
|
||||
* when the target is this contract.
|
||||
*
|
||||
* Returns:
|
||||
* - bool immediate: whether the operation can be executed immediately (with no delay)
|
||||
* - uint32 delay: the execution delay
|
||||
*
|
||||
* If immediate is true, the delay can be disregarded and the operation can be immediately executed.
|
||||
* If immediate is false, the operation can be executed if and only if delay is greater than 0.
|
||||
*/
|
||||
function _canCallExtended(address caller, address target, bytes calldata data) private view returns (bool, uint32) {
|
||||
function _canCallExtended(
|
||||
address caller,
|
||||
address target,
|
||||
bytes calldata data
|
||||
) private view returns (bool immediate, uint32 delay) {
|
||||
if (target == address(this)) {
|
||||
return _canCallSelf(caller, data);
|
||||
} else {
|
||||
bytes4 selector = bytes4(data);
|
||||
return canCall(caller, target, selector);
|
||||
return data.length < 4 ? (false, 0) : canCall(caller, target, _checkSelector(data));
|
||||
}
|
||||
}
|
||||
|
||||
@ -844,10 +675,14 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
* @dev A version of {canCall} that checks for admin restrictions in this contract.
|
||||
*/
|
||||
function _canCallSelf(address caller, bytes calldata data) private view returns (bool immediate, uint32 delay) {
|
||||
if (data.length < 4) {
|
||||
return (false, 0);
|
||||
}
|
||||
|
||||
if (caller == address(this)) {
|
||||
// Caller is AccessManager, this means the call was sent through {execute} and it already checked
|
||||
// permissions. We verify that the call "identifier", which is set during {execute}, is correct.
|
||||
return (_isExecuting(address(this), bytes4(data)), 0);
|
||||
return (_isExecuting(address(this), _checkSelector(data)), 0);
|
||||
}
|
||||
|
||||
(bool enabled, uint64 roleId, uint32 operationDelay) = _getAdminRestrictions(data);
|
||||
@ -878,4 +713,18 @@ contract AccessManager is Context, Multicall, IAccessManager {
|
||||
function _isExpired(uint48 timepoint) private view returns (bool) {
|
||||
return timepoint + expiration() <= Time.timestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extracts the selector from calldata. Panics if data is not at least 4 bytes
|
||||
*/
|
||||
function _checkSelector(bytes calldata data) private pure returns (bytes4) {
|
||||
return bytes4(data[0:4]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Hashing function for execute protection
|
||||
*/
|
||||
function _hashExecutionId(address target, bytes4 selector) private pure returns (bytes32) {
|
||||
return keccak256(abi.encode(target, selector));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v5.0.0) (access/manager/AuthorityUtils.sol)
|
||||
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user