diff --git a/CHANGELOG.md b/CHANGELOG.md index 90361a02500..fba31952578 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,7 @@ ### Pragma changes -- Reduced pragma requirement of interface files +- Reduced pragma requirement of interface files. ### Changes by category diff --git a/contracts/metatx/ERC2771Forwarder.sol b/contracts/metatx/ERC2771Forwarder.sol index 3ba53222557..c27067171db 100644 --- a/contracts/metatx/ERC2771Forwarder.sol +++ b/contracts/metatx/ERC2771Forwarder.sol @@ -19,7 +19,7 @@ import {Errors} from "../utils/Errors.sol"; * * `to`: The address that should be called. * * `value`: The amount of native token to attach with the requested call. * * `gas`: The amount of gas limit that will be forwarded with the requested call. - * * `nonce`: A unique transaction ordering identifier to avoid replayability and request invalidation. + * * `nonce` (implicit): Taken from {Nonces} for `from` and included in the signed typed data. * * `deadline`: A timestamp after which the request is not executable anymore. * * `data`: Encoded `msg.data` to send with the requested call. * @@ -195,7 +195,7 @@ contract ERC2771Forwarder is EIP712, Nonces { /** * @dev Validates if the provided request can be executed at current block timestamp with - * the given `request.signature` on behalf of `request.signer`. + * the given `request.signature` on behalf of `request.from`. */ function _validate( ForwardRequestData calldata request diff --git a/contracts/mocks/docs/ERC4626Fees.sol b/contracts/mocks/docs/ERC4626Fees.sol index b8ee33f3326..5c0b05309c5 100644 --- a/contracts/mocks/docs/ERC4626Fees.sol +++ b/contracts/mocks/docs/ERC4626Fees.sol @@ -57,7 +57,7 @@ abstract contract ERC4626Fees is ERC4626 { } } - /// @dev Send exit fee to {_exitFeeRecipient}. See {IERC4626-_deposit}. + /// @dev Send exit fee to {_exitFeeRecipient}. See {IERC4626-_withdraw}. function _withdraw( address caller, address receiver, diff --git a/contracts/token/ERC20/extensions/ERC4626.sol b/contracts/token/ERC20/extensions/ERC4626.sol index 08760a70618..bd199335459 100644 --- a/contracts/token/ERC20/extensions/ERC4626.sol +++ b/contracts/token/ERC20/extensions/ERC4626.sol @@ -84,12 +84,12 @@ abstract contract ERC4626 is ERC20, IERC4626 { error ERC4626ExceededMaxMint(address receiver, uint256 shares, uint256 max); /** - * @dev Attempted to withdraw more assets than the max amount for `receiver`. + * @dev Attempted to withdraw more assets than the max amount for `owner`. */ error ERC4626ExceededMaxWithdraw(address owner, uint256 assets, uint256 max); /** - * @dev Attempted to redeem more shares than the max amount for `receiver`. + * @dev Attempted to redeem more shares than the max amount for `owner`. */ error ERC4626ExceededMaxRedeem(address owner, uint256 shares, uint256 max); diff --git a/contracts/utils/cryptography/SignatureChecker.sol b/contracts/utils/cryptography/SignatureChecker.sol index 036be785eb4..bb776137f75 100644 --- a/contracts/utils/cryptography/SignatureChecker.sol +++ b/contracts/utils/cryptography/SignatureChecker.sol @@ -73,8 +73,8 @@ library SignatureChecker { // Encoded calldata is : // [ 0x00 - 0x03 ] // [ 0x04 - 0x23 ] - // [ 0x24 - 0x44 ] (0x40) - // [ 0x44 - 0x64 ] + // [ 0x24 - 0x43 ] (0x40) + // [ 0x44 - 0x63 ] // [ 0x64 - ... ] let ptr := mload(0x40) mstore(ptr, selector) diff --git a/contracts/utils/math/SafeCast.sol b/contracts/utils/math/SafeCast.sol index b345ede1e69..5b4f23cc98d 100644 --- a/contracts/utils/math/SafeCast.sol +++ b/contracts/utils/math/SafeCast.sol @@ -18,12 +18,12 @@ pragma solidity ^0.8.20; */ library SafeCast { /** - * @dev Value doesn't fit in an uint of `bits` size. + * @dev Value doesn't fit in a uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** - * @dev An int value doesn't fit in an uint of `bits` size. + * @dev An int value doesn't fit in a uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); @@ -33,7 +33,7 @@ library SafeCast { error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** - * @dev An uint value doesn't fit in an int of `bits` size. + * @dev A uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); diff --git a/docs/modules/ROOT/pages/access-control.adoc b/docs/modules/ROOT/pages/access-control.adoc index d8b8cdb78c1..a9c5cf5586e 100644 --- a/docs/modules/ROOT/pages/access-control.adoc +++ b/docs/modules/ROOT/pages/access-control.adoc @@ -31,7 +31,7 @@ In this way, you can use _composability_ to add additional layers of access cont [[role-based-access-control]] == Role-Based Access Control -While the simplicity of _ownership_ can be useful for simple systems or quick prototyping, different levels of authorization are often needed. You may want for an account to have permission to ban users from a system, but not create new tokens. https://en.wikipedia.org/wiki/Role-based_access_control[_Role-Based Access Control (RBAC)_] offers flexibility in this regard. +While the simplicity of _ownership_ can be useful for simple systems or quick prototyping, different levels of authorization are often needed. You may want an account to have permission to ban users from a system, but not create new tokens. https://en.wikipedia.org/wiki/Role-based_access_control[_Role-Based Access Control (RBAC)_] offers flexibility in this regard. In essence, we will be defining multiple _roles_, each allowed to perform different sets of actions. An account may have, for example, 'moderator', 'minter' or 'admin' roles, which you will then check for instead of simply using `onlyOwner`. This check can be enforced through the `onlyRole` modifier. Separately, you will be able to define rules for how accounts can be granted a role, have it revoked, and more. @@ -74,7 +74,7 @@ Every role has an associated admin role, which grants permission to call the `gr This mechanism can be used to create complex permissioning structures resembling organizational charts, but it also provides an easy way to manage simpler applications. `AccessControl` includes a special role, called `DEFAULT_ADMIN_ROLE`, which acts as the **default admin role for all roles**. An account with this role will be able to manage any other role, unless `_setRoleAdmin` is used to select a new admin role. -Since it is the admin for all roles by default, and in fact it is also its own admin, this role carries significant risk. To mitigate this risk we provide xref:api:access.adoc#AccessControlDefaultAdminRules[`AccessControlDefaultAdminRules`], a recommended extension of `AccessControl` that adds a number of enforced security measures for this role: the admin is restricted to a single account, with a 2-step transfer procedure with a delay in between steps. +Since it is the admin for all roles by default, and in fact it is also its own admin, this role carries significant risk. To mitigate this risk we provide xref:api:access.adoc#AccessControlDefaultAdminRules[`AccessControlDefaultAdminRules`], a recommended extension of `AccessControl` that adds a number of enforced security measures for this role: the admin is restricted to a single account, with a 2-step transfer procedure with a delay between steps. Let's take a look at the ERC-20 token example, this time taking advantage of the default admin role: @@ -199,7 +199,7 @@ await manager.setTargetFunctionRole( ); ``` -Even though each role has its own list of function permissions, each role member (`address`) has an execution delay that will dictate how long the account should wait to execute a function that requires its role. Delayed operations must have the xref:api:access.adoc#AccessManager-schedule-address-bytes-uint48-[`schedule`] function called on them first in the AccessManager before they can be executed, either by calling to the target function or using the AccessManager's xref:api:access.adoc#AccessManager-execute-address-bytes-[`execute`] function. +Even though each role has its own list of function permissions, each role member (`address`) has an execution delay that will dictate how long the account should wait to execute a function that requires its role. Delayed operations must have the xref:api:access.adoc#AccessManager-schedule-address-bytes-uint48-[`schedule`] function called on them first in the AccessManager before they can be executed, either by calling the target function or using the AccessManager's xref:api:access.adoc#AccessManager-execute-address-bytes-[`execute`] function. Additionally, roles can have a granting delay that prevents adding members immediately. The AccessManager admins can set this grant delay as follows: @@ -293,3 +293,5 @@ await accessControl.connect(admin).grantRole(DEFAULT_ADMIN_ROLE, accessManager); await accessControl.connect(admin).renounceRole(DEFAULT_ADMIN_ROLE, admin); ``` + +NOTE: After migrating to AccessManager, the `msg.sender` in restricted functions will be the AccessManager contract itself through the xref:api:access.adoc#AccessManager-execute-address-bytes-[`execute`] function, not the original caller. This is a fundamental change in how access control works and may require updates to your contract logic or frontend integration. diff --git a/docs/modules/ROOT/pages/accounts.adoc b/docs/modules/ROOT/pages/accounts.adoc index 5d42eaf36ac..68d14cc6038 100644 --- a/docs/modules/ROOT/pages/accounts.adoc +++ b/docs/modules/ROOT/pages/accounts.adoc @@ -2,11 +2,11 @@ OpenZeppelin provides a simple xref:api:account.adoc#Account[`Account`] implementation including only the basic logic to handle user operations in compliance with ERC-4337. Developers who want to build their own account can leverage it to bootstrap custom implementations. -User operations are validated using an xref:api:utils.adoc#AbstractSigner[`AbstractSigner`], which requires to implement the internal xref:api:utils.adoc#AbstractSigner-_rawSignatureValidation-bytes32-bytes-[`_rawSignatureValidation`] function, of which we offer a set of implementations to cover a wide customization range. This is the lowest-level signature validation layer and is used to wrap other validation methods like the Account's xref:api:account.adoc#Account-validateUserOp-struct-PackedUserOperation-bytes32-uint256-[`validateUserOp`]. +User operations are validated using an xref:api:utils.adoc#AbstractSigner[`AbstractSigner`], which requires implementing the internal xref:api:utils.adoc#AbstractSigner-_rawSignatureValidation-bytes32-bytes-[`_rawSignatureValidation`] function, of which we offer a set of implementations to cover a wide customization range. This is the lowest-level signature validation layer and is used to wrap other validation methods like the Account's xref:api:account.adoc#Account-validateUserOp-struct-PackedUserOperation-bytes32-uint256-[`validateUserOp`]. == Setting up an account -To setup an account, you can either start configuring it using our Wizard and selecting a predefined validation scheme, or bring your own logic and start by inheriting xref:api:account.adoc#Account[`Account`] from scratch. +To set up an account, you can either start configuring it using our Wizard and selecting a predefined validation scheme, or bring your own logic and start by inheriting xref:api:account.adoc#Account[`Account`] from scratch. ++++ @@ -25,7 +25,7 @@ Since the minimum requirement of xref:api:account.adoc#Account[`Account`] is to * xref:api:utils/cryptography.adoc#SignerRSA[`SignerRSA`]: Verifies signatures of traditional PKI systems and X.509 certificates. * xref:api:utils/cryptography.adoc#SignerEIP7702[`SignerEIP7702`]: Checks EOA signatures delegated to this signer using https://eips.ethereum.org/EIPS/eip-7702#set-code-transaction[EIP-7702 authorizations] * xref:api:utils/cryptography.adoc#SignerERC7913[`SignerERC7913`]: Verifies generalized signatures following https://eips.ethereum.org/EIPS/eip-7913[ERC-7913]. -* https://docs.openzeppelin.com/community-contracts/0.0.1/api/utils#SignerZKEmail[`SignerZKEmail`]: Enables email-based authentication for smart contracts using zero knowledge proofs of email authority signatures. +* https://docs.openzeppelin.com/community-contracts/0.0.1/api/utils#SignerZKEmail[`SignerZKEmail`]: Enables email-based authentication for smart contracts using zero-knowledge proofs of email authority signatures. * xref:api:utils/cryptography.adoc#MultiSignerERC7913[`MultiSignerERC7913`]: Allows using multiple ERC-7913 signers with a threshold-based signature verification system. * xref:api:utils/cryptography.adoc#MultiSignerERC7913Weighted[`MultiSignerERC7913Weighted`]: Overrides the threshold mechanism of xref:api:utils/cryptography.adoc#MultiSignerERC7913[`MultiSignerERC7913`], offering different weights per signer. @@ -153,7 +153,7 @@ const userOpData = encodeFunctionData({ == Bundle a `UserOperation` -xref:account-abstraction.adoc#useroperation[UserOperations] are a powerful abstraction layer that enable more sophisticated transaction capabilities compared to traditional Ethereum transactions. To get started, you'll need to an account, which you can get by xref:accounts.adoc#accounts_factory[deploying a factory] for your implementation. +xref:account-abstraction.adoc#useroperation[UserOperations] are a powerful abstraction layer that enable more sophisticated transaction capabilities compared to traditional Ethereum transactions. To get started, you'll need an account, which you can get by xref:accounts.adoc#accounts_factory[deploying a factory] for your implementation. === Preparing a UserOp diff --git a/scripts/generate/templates/SafeCast.js b/scripts/generate/templates/SafeCast.js index 21000cf4a62..16d1ee8f7f1 100644 --- a/scripts/generate/templates/SafeCast.js +++ b/scripts/generate/templates/SafeCast.js @@ -22,12 +22,12 @@ pragma solidity ^0.8.20; const errors = `\ /** - * @dev Value doesn't fit in an uint of \`bits\` size. + * @dev Value doesn't fit in a uint of \`bits\` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** - * @dev An int value doesn't fit in an uint of \`bits\` size. + * @dev An int value doesn't fit in a uint of \`bits\` size. */ error SafeCastOverflowedIntToUint(int256 value); @@ -37,7 +37,7 @@ error SafeCastOverflowedIntToUint(int256 value); error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** - * @dev An uint value doesn't fit in an int of \`bits\` size. + * @dev A uint value doesn't fit in an int of \`bits\` size. */ error SafeCastOverflowedUintToInt(uint256 value); `; diff --git a/scripts/minimize-pragma.js b/scripts/minimize-pragma.js index fc6606df3a7..a4cbf03aa77 100755 --- a/scripts/minimize-pragma.js +++ b/scripts/minimize-pragma.js @@ -37,7 +37,9 @@ const limit = pLimit(concurrency); const updatePragma = (file, pragma) => fs.writeFileSync( file, - fs.readFileSync(file, 'utf8').replace(/pragma solidity [><=^]*[0-9]+.[0-9]+.[0-9]+;/, `pragma solidity ${pragma};`), + fs + .readFileSync(file, 'utf8') + .replace(/pragma solidity [><=^]*[0-9]+\.[0-9]+\.[0-9]+;/, `pragma solidity ${pragma};`), 'utf8', ); diff --git a/test/access/manager/AccessManaged.test.js b/test/access/manager/AccessManaged.test.js index d666b5e6dcc..d69b568ff4c 100644 --- a/test/access/manager/AccessManaged.test.js +++ b/test/access/manager/AccessManaged.test.js @@ -65,7 +65,7 @@ describe('AccessManaged', function () { describe('when role is granted with execution delay', function () { beforeEach(async function () { - const executionDelay = 911n; + const executionDelay = 911n; // Arbitrary delay for testing execution delay functionality await this.authority.$_grantRole(this.role, this.roleMember, 0, executionDelay); });