更新合约文档,翻译为中文以增强可读性,包括 AccessControl、Ownable、ERC20 和 IERC20 的相关说明。修正了一些注释以确保准确性和一致性。
Some checks failed
transpile upgradeable / transpile (push) Has been cancelled
Some checks failed
transpile upgradeable / transpile (push) Has been cancelled
This commit is contained in:
@ -8,22 +8,18 @@ import {Context} from "../utils/Context.sol";
|
||||
import {IERC165, ERC165} from "../utils/introspection/ERC165.sol";
|
||||
|
||||
/**
|
||||
* @dev Contract module that allows children to implement role-based access
|
||||
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
|
||||
* members except through off-chain means by accessing the contract event logs. Some
|
||||
* applications may benefit from on-chain enumerability, for those cases see
|
||||
* {AccessControlEnumerable}.
|
||||
* @dev 合约模块,允许子合约实现基于角色的访问控制机制。这是一个轻量级版本,
|
||||
* 不允许枚举角色成员,除非通过链下方式访问合约事件日志。某些应用可能会受益于链上可枚举性,
|
||||
* 对于这些情况,请参见 {AccessControlEnumerable}。
|
||||
*
|
||||
* Roles are referred to by their `bytes32` identifier. These should be exposed
|
||||
* in the external API and be unique. The best way to achieve this is by
|
||||
* using `public constant` hash digests:
|
||||
* 角色通过其 `bytes32` 标识符来引用。这些应该在外部 API 中公开并且是唯一的。
|
||||
* 实现这一点的最佳方法是使用 `public constant` 哈希摘要:
|
||||
*
|
||||
* ```solidity
|
||||
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
|
||||
* ```
|
||||
*
|
||||
* Roles can be used to represent a set of permissions. To restrict access to a
|
||||
* function call, use {hasRole}:
|
||||
* 角色可以用来表示一组权限。要限制对函数调用的访问,请使用 {hasRole}:
|
||||
*
|
||||
* ```solidity
|
||||
* function foo() public {
|
||||
@ -32,19 +28,15 @@ import {IERC165, ERC165} from "../utils/introspection/ERC165.sol";
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Roles can be granted and revoked dynamically via the {grantRole} and
|
||||
* {revokeRole} functions. Each role has an associated admin role, and only
|
||||
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
|
||||
* 角色可以通过 {grantRole} 和 {revokeRole} 函数动态授予和撤销。每个角色都有一个关联的管理员角色,
|
||||
* 只有具有角色管理员角色的账户才能调用 {grantRole} 和 {revokeRole}。
|
||||
*
|
||||
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
|
||||
* that only accounts with this role will be able to grant or revoke other
|
||||
* roles. More complex role relationships can be created by using
|
||||
* {_setRoleAdmin}.
|
||||
* 默认情况下,所有角色的管理员角色是 `DEFAULT_ADMIN_ROLE`,这意味着只有具有此角色的账户
|
||||
* 才能授予或撤销其他角色。可以使用 {_setRoleAdmin} 创建更复杂的角色关系。
|
||||
*
|
||||
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
|
||||
* grant and revoke this role. Extra precautions should be taken to secure
|
||||
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
|
||||
* to enforce additional security measures for this role.
|
||||
* 警告:`DEFAULT_ADMIN_ROLE` 也是其自身的管理员:它有权限授予和撤销这个角色。
|
||||
* 应该采取额外的预防措施来保护已被授予此角色的账户。我们建议使用 {AccessControlDefaultAdminRules}
|
||||
* 来为此角色强制执行额外的安全措施。
|
||||
*/
|
||||
abstract contract AccessControl is Context, IAccessControl, ERC165 {
|
||||
struct RoleData {
|
||||
@ -57,8 +49,8 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
|
||||
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
|
||||
|
||||
/**
|
||||
* @dev Modifier that checks that an account has a specific role. Reverts
|
||||
* with an {AccessControlUnauthorizedAccount} error including the required role.
|
||||
* @dev 检查账户是否具有特定角色的修饰符。如果没有,则使用 {AccessControlUnauthorizedAccount} 错误
|
||||
* 回退,包括所需的角色。
|
||||
*/
|
||||
modifier onlyRole(bytes32 role) {
|
||||
_checkRole(role);
|
||||
@ -71,23 +63,22 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns `true` if `account` has been granted `role`.
|
||||
* @dev 如果 `account` 已被授予 `role`,则返回 `true`。
|
||||
*/
|
||||
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
|
||||
return _roles[role].hasRole[account];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
|
||||
* is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
|
||||
* @dev 如果 `_msgSender()` 缺少 `role`,则使用 {AccessControlUnauthorizedAccount} 错误回退。
|
||||
* 重写此函数会改变 {onlyRole} 修饰符的行为。
|
||||
*/
|
||||
function _checkRole(bytes32 role) internal view virtual {
|
||||
_checkRole(role, _msgSender());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
|
||||
* is missing `role`.
|
||||
* @dev 如果 `account` 缺少 `role`,则使用 {AccessControlUnauthorizedAccount} 错误回退。
|
||||
*/
|
||||
function _checkRole(bytes32 role, address account) internal view virtual {
|
||||
if (!hasRole(role, account)) {
|
||||
@ -96,61 +87,57 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the admin role that controls `role`. See {grantRole} and
|
||||
* {revokeRole}.
|
||||
* @dev 返回控制 `role` 的管理员角色。请参见 {grantRole} 和 {revokeRole}。
|
||||
*
|
||||
* To change a role's admin, use {_setRoleAdmin}.
|
||||
* 要更改角色的管理员,请使用 {_setRoleAdmin}。
|
||||
*/
|
||||
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
|
||||
return _roles[role].adminRole;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Grants `role` to `account`.
|
||||
* @dev 将 `role` 授予给 `account`。
|
||||
*
|
||||
* If `account` had not been already granted `role`, emits a {RoleGranted}
|
||||
* event.
|
||||
* 如果 `account` 尚未被授予 `role`,则发出 {RoleGranted} 事件。
|
||||
*
|
||||
* Requirements:
|
||||
* 要求:
|
||||
*
|
||||
* - the caller must have ``role``'s admin role.
|
||||
* - 调用者必须具有 `role` 的管理员角色。
|
||||
*
|
||||
* May emit a {RoleGranted} event.
|
||||
* 可能发出 {RoleGranted} 事件。
|
||||
*/
|
||||
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
|
||||
_grantRole(role, account);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Revokes `role` from `account`.
|
||||
* @dev 从 `account` 撤销 `role`。
|
||||
*
|
||||
* If `account` had been granted `role`, emits a {RoleRevoked} event.
|
||||
* 如果 `account` 已被授予 `role`,则发出 {RoleRevoked} 事件。
|
||||
*
|
||||
* Requirements:
|
||||
* 要求:
|
||||
*
|
||||
* - the caller must have ``role``'s admin role.
|
||||
* - 调用者必须具有 `role` 的管理员角色。
|
||||
*
|
||||
* May emit a {RoleRevoked} event.
|
||||
* 可能发出 {RoleRevoked} 事件。
|
||||
*/
|
||||
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
|
||||
_revokeRole(role, account);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Revokes `role` from the calling account.
|
||||
* @dev 从调用账户撤销 `role`。
|
||||
*
|
||||
* Roles are often managed via {grantRole} and {revokeRole}: this function's
|
||||
* purpose is to provide a mechanism for accounts to lose their privileges
|
||||
* if they are compromised (such as when a trusted device is misplaced).
|
||||
* 角色通常通过 {grantRole} 和 {revokeRole} 进行管理:此函数的目的是为账户提供一种机制,
|
||||
* 在它们受到损害时(例如当受信任的设备丢失时)失去其特权。
|
||||
*
|
||||
* If the calling account had been revoked `role`, emits a {RoleRevoked}
|
||||
* event.
|
||||
* 如果调用账户的 `role` 已被撤销,则发出 {RoleRevoked} 事件。
|
||||
*
|
||||
* Requirements:
|
||||
* 要求:
|
||||
*
|
||||
* - the caller must be `callerConfirmation`.
|
||||
* - 调用者必须是 `callerConfirmation`。
|
||||
*
|
||||
* May emit a {RoleRevoked} event.
|
||||
* 可能发出 {RoleRevoked} 事件。
|
||||
*/
|
||||
function renounceRole(bytes32 role, address callerConfirmation) public virtual {
|
||||
if (callerConfirmation != _msgSender()) {
|
||||
@ -161,9 +148,9 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Sets `adminRole` as ``role``'s admin role.
|
||||
* @dev 将 `adminRole` 设置为 `role` 的管理员角色。
|
||||
*
|
||||
* Emits a {RoleAdminChanged} event.
|
||||
* 发出 {RoleAdminChanged} 事件。
|
||||
*/
|
||||
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
|
||||
bytes32 previousAdminRole = getRoleAdmin(role);
|
||||
@ -172,11 +159,11 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
|
||||
* @dev 尝试将 `role` 授予给 `account` 并返回一个布尔值,指示是否授予了 `role`。
|
||||
*
|
||||
* Internal function without access restriction.
|
||||
* 内部函数,无访问限制。
|
||||
*
|
||||
* May emit a {RoleGranted} event.
|
||||
* 可能发出 {RoleGranted} 事件。
|
||||
*/
|
||||
function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
|
||||
if (!hasRole(role, account)) {
|
||||
@ -189,11 +176,11 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.
|
||||
* @dev 尝试从 `account` 撤销 `role` 并返回一个布尔值,指示是否撤销了 `role`。
|
||||
*
|
||||
* Internal function without access restriction.
|
||||
* 内部函数,无访问限制。
|
||||
*
|
||||
* May emit a {RoleRevoked} event.
|
||||
* 可能发出 {RoleRevoked} 事件。
|
||||
*/
|
||||
function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
|
||||
if (hasRole(role, account)) {
|
||||
|
||||
@ -6,34 +6,29 @@ pragma solidity ^0.8.20;
|
||||
import {Context} from "../utils/Context.sol";
|
||||
|
||||
/**
|
||||
* @dev Contract module which provides a basic access control mechanism, where
|
||||
* there is an account (an owner) that can be granted exclusive access to
|
||||
* specific functions.
|
||||
* @dev 合约模块,提供基本的访问控制机制,其中有一个账户(所有者)可以被授予对特定函数的独占访问权限。
|
||||
*
|
||||
* The initial owner is set to the address provided by the deployer. This can
|
||||
* later be changed with {transferOwnership}.
|
||||
* 初始所有者设置为部署者提供的地址。这可以稍后通过 {transferOwnership} 更改。
|
||||
*
|
||||
* This module is used through inheritance. It will make available the modifier
|
||||
* `onlyOwner`, which can be applied to your functions to restrict their use to
|
||||
* the owner.
|
||||
* 此模块通过继承使用。它将提供修饰符 `onlyOwner`,可以应用于您的函数以限制它们仅供所有者使用。
|
||||
*/
|
||||
abstract contract Ownable is Context {
|
||||
address private _owner;
|
||||
|
||||
/**
|
||||
* @dev The caller account is not authorized to perform an operation.
|
||||
* @dev 调用者账户未被授权执行操作。
|
||||
*/
|
||||
error OwnableUnauthorizedAccount(address account);
|
||||
|
||||
/**
|
||||
* @dev The owner is not a valid owner account. (eg. `address(0)`)
|
||||
* @dev 所有者不是有效的所有者账户。(例如 `address(0)`)
|
||||
*/
|
||||
error OwnableInvalidOwner(address owner);
|
||||
|
||||
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
|
||||
|
||||
/**
|
||||
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
|
||||
* @dev 初始化合约,将部署者提供的地址设置为初始所有者。
|
||||
*/
|
||||
constructor(address initialOwner) {
|
||||
if (initialOwner == address(0)) {
|
||||
@ -43,7 +38,7 @@ abstract contract Ownable is Context {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Throws if called by any account other than the owner.
|
||||
* @dev 如果由所有者以外的任何账户调用则抛出异常。
|
||||
*/
|
||||
modifier onlyOwner() {
|
||||
_checkOwner();
|
||||
@ -51,14 +46,14 @@ abstract contract Ownable is Context {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the address of the current owner.
|
||||
* @dev 返回当前所有者的地址。
|
||||
*/
|
||||
function owner() public view virtual returns (address) {
|
||||
return _owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Throws if the sender is not the owner.
|
||||
* @dev 如果发送者不是所有者则抛出异常。
|
||||
*/
|
||||
function _checkOwner() internal view virtual {
|
||||
if (owner() != _msgSender()) {
|
||||
@ -67,19 +62,16 @@ abstract contract Ownable is Context {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Leaves the contract without owner. It will not be possible to call
|
||||
* `onlyOwner` functions. Can only be called by the current owner.
|
||||
* @dev 使合约没有所有者。将无法调用 `onlyOwner` 函数。只能由当前所有者调用。
|
||||
*
|
||||
* NOTE: Renouncing ownership will leave the contract without an owner,
|
||||
* thereby disabling any functionality that is only available to the owner.
|
||||
* 注意:放弃所有权将使合约没有所有者,从而禁用仅对所有者可用的任何功能。
|
||||
*/
|
||||
function renounceOwnership() public virtual onlyOwner {
|
||||
_transferOwnership(address(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Transfers ownership of the contract to a new account (`newOwner`).
|
||||
* Can only be called by the current owner.
|
||||
* @dev 将合约的所有权转移给新账户 (`newOwner`)。只能由当前所有者调用。
|
||||
*/
|
||||
function transferOwnership(address newOwner) public virtual onlyOwner {
|
||||
if (newOwner == address(0)) {
|
||||
@ -89,8 +81,7 @@ abstract contract Ownable is Context {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Transfers ownership of the contract to a new account (`newOwner`).
|
||||
* Internal function without access restriction.
|
||||
* @dev 将合约的所有权转移给新账户 (`newOwner`)。内部函数,无访问限制。
|
||||
*/
|
||||
function _transferOwnership(address newOwner) internal virtual {
|
||||
address oldOwner = _owner;
|
||||
|
||||
@ -9,22 +9,17 @@ import {Context} from "../../utils/Context.sol";
|
||||
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";
|
||||
|
||||
/**
|
||||
* @dev Implementation of the {IERC20} interface.
|
||||
* @dev {IERC20} 接口的实现。
|
||||
*
|
||||
* This implementation is agnostic to the way tokens are created. This means
|
||||
* that a supply mechanism has to be added in a derived contract using {_mint}.
|
||||
* 此实现与代币创建方式无关。这意味着必须在派生合约中使用 {_mint} 添加供应机制。
|
||||
*
|
||||
* TIP: For a detailed writeup see our guide
|
||||
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
|
||||
* to implement supply mechanisms].
|
||||
* 提示:有关详细说明,请参阅我们的指南
|
||||
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[如何实现供应机制]。
|
||||
*
|
||||
* The default value of {decimals} is 18. To change this, you should override
|
||||
* this function so it returns a different value.
|
||||
* {decimals} 的默认值是 18。要更改此值,您应该重写此函数以返回不同的值。
|
||||
*
|
||||
* We have followed general OpenZeppelin Contracts guidelines: functions revert
|
||||
* instead returning `false` on failure. This behavior is nonetheless
|
||||
* conventional and does not conflict with the expectations of ERC-20
|
||||
* applications.
|
||||
* 我们遵循了 OpenZeppelin 合约的一般准则:函数在失败时回退而不是返回 `false`。
|
||||
* 这种行为仍然是常规的,并且不会与 ERC-20 应用程序的期望冲突。
|
||||
*/
|
||||
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
|
||||
mapping(address account => uint256) private _balances;
|
||||
@ -37,9 +32,9 @@ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
|
||||
string private _symbol;
|
||||
|
||||
/**
|
||||
* @dev Sets the values for {name} and {symbol}.
|
||||
* @dev 设置 {name} 和 {symbol} 的值。
|
||||
*
|
||||
* Both values are immutable: they can only be set once during construction.
|
||||
* 这两个值都是不可变的:它们只能在构造期间设置一次。
|
||||
*/
|
||||
constructor(string memory name_, string memory symbol_) {
|
||||
_name = name_;
|
||||
@ -47,32 +42,27 @@ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the name of the token.
|
||||
* @dev 返回代币的名称。
|
||||
*/
|
||||
function name() public view virtual returns (string memory) {
|
||||
return _name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the symbol of the token, usually a shorter version of the
|
||||
* name.
|
||||
* @dev 返回代币的符号,通常是名称的较短版本。
|
||||
*/
|
||||
function symbol() public view virtual returns (string memory) {
|
||||
return _symbol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the number of decimals used to get its user representation.
|
||||
* For example, if `decimals` equals `2`, a balance of `505` tokens should
|
||||
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
|
||||
* @dev 返回用于获取其用户表示的小数位数。
|
||||
* 例如,如果 `decimals` 等于 `2`,则应该向用户显示 `505` 代币的余额为 `5.05` (`505 / 10 ** 2`)。
|
||||
*
|
||||
* Tokens usually opt for a value of 18, imitating the relationship between
|
||||
* Ether and Wei. This is the default value returned by this function, unless
|
||||
* it's overridden.
|
||||
* 代币通常选择值为 18,模仿以太币和 Wei 之间的关系。除非被重写,否则这是此函数返回的默认值。
|
||||
*
|
||||
* NOTE: This information is only used for _display_ purposes: it in
|
||||
* no way affects any of the arithmetic of the contract, including
|
||||
* {IERC20-balanceOf} and {IERC20-transfer}.
|
||||
* 注意:此信息仅用于 _显示_ 目的:它不会以任何方式影响合约的任何算术,
|
||||
* 包括 {IERC20-balanceOf} 和 {IERC20-transfer}。
|
||||
*/
|
||||
function decimals() public view virtual returns (uint8) {
|
||||
return 18;
|
||||
@ -89,12 +79,12 @@ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev See {IERC20-transfer}.
|
||||
* @dev 参见 {IERC20-transfer}。
|
||||
*
|
||||
* Requirements:
|
||||
* 要求:
|
||||
*
|
||||
* - `to` cannot be the zero address.
|
||||
* - the caller must have a balance of at least `value`.
|
||||
* - `to` 不能是零地址。
|
||||
* - 调用者必须有至少 `value` 的余额。
|
||||
*/
|
||||
function transfer(address to, uint256 value) public virtual returns (bool) {
|
||||
address owner = _msgSender();
|
||||
@ -108,14 +98,14 @@ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev See {IERC20-approve}.
|
||||
* @dev 参见 {IERC20-approve}。
|
||||
*
|
||||
* NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
|
||||
* `transferFrom`. This is semantically equivalent to an infinite approval.
|
||||
* 注意:如果 `value` 是最大 `uint256`,则在 `transferFrom` 时不会更新授权额度。
|
||||
* 这在语义上等同于无限授权。
|
||||
*
|
||||
* Requirements:
|
||||
* 要求:
|
||||
*
|
||||
* - `spender` cannot be the zero address.
|
||||
* - `spender` 不能是零地址。
|
||||
*/
|
||||
function approve(address spender, uint256 value) public virtual returns (bool) {
|
||||
address owner = _msgSender();
|
||||
@ -124,20 +114,18 @@ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev See {IERC20-transferFrom}.
|
||||
* @dev 参见 {IERC20-transferFrom}。
|
||||
*
|
||||
* Skips emitting an {Approval} event indicating an allowance update. This is not
|
||||
* required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
|
||||
* 跳过发出 {Approval} 事件以指示授权额度更新。ERC 不要求这样做。
|
||||
* 参见 {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]。
|
||||
*
|
||||
* NOTE: Does not update the allowance if the current allowance
|
||||
* is the maximum `uint256`.
|
||||
* 注意:如果当前授权额度是最大 `uint256`,则不会更新授权额度。
|
||||
*
|
||||
* Requirements:
|
||||
* 要求:
|
||||
*
|
||||
* - `from` and `to` cannot be the zero address.
|
||||
* - `from` must have a balance of at least `value`.
|
||||
* - the caller must have allowance for ``from``'s tokens of at least
|
||||
* `value`.
|
||||
* - `from` 和 `to` 不能是零地址。
|
||||
* - `from` 必须有至少 `value` 的余额。
|
||||
* - 调用者必须对 `from` 的代币有至少 `value` 的授权额度。
|
||||
*/
|
||||
function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
|
||||
address spender = _msgSender();
|
||||
|
||||
@ -4,76 +4,70 @@
|
||||
pragma solidity >=0.4.16;
|
||||
|
||||
/**
|
||||
* @dev Interface of the ERC-20 standard as defined in the ERC.
|
||||
* @dev ERC-20 标准的接口,如 ERC 中定义的那样。
|
||||
*/
|
||||
interface IERC20 {
|
||||
/**
|
||||
* @dev Emitted when `value` tokens are moved from one account (`from`) to
|
||||
* another (`to`).
|
||||
* @dev 当 `value` 个代币从一个账户 (`from`) 转移到另一个账户 (`to`) 时发出。
|
||||
*
|
||||
* Note that `value` may be zero.
|
||||
* 注意 `value` 可能为零。
|
||||
*/
|
||||
event Transfer(address indexed from, address indexed to, uint256 value);
|
||||
|
||||
/**
|
||||
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
|
||||
* a call to {approve}. `value` is the new allowance.
|
||||
* @dev 当通过调用 {approve} 设置 `spender` 对 `owner` 的授权额度时发出。
|
||||
* `value` 是新的授权额度。
|
||||
*/
|
||||
event Approval(address indexed owner, address indexed spender, uint256 value);
|
||||
|
||||
/**
|
||||
* @dev Returns the value of tokens in existence.
|
||||
* @dev 返回现存代币的数量。
|
||||
*/
|
||||
function totalSupply() external view returns (uint256);
|
||||
|
||||
/**
|
||||
* @dev Returns the value of tokens owned by `account`.
|
||||
* @dev 返回 `account` 拥有的代币数量。
|
||||
*/
|
||||
function balanceOf(address account) external view returns (uint256);
|
||||
|
||||
/**
|
||||
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
|
||||
* @dev 从调用者的账户向 `to` 转移 `value` 数量的代币。
|
||||
*
|
||||
* Returns a boolean value indicating whether the operation succeeded.
|
||||
* 返回一个布尔值,指示操作是否成功。
|
||||
*
|
||||
* Emits a {Transfer} event.
|
||||
* 发出 {Transfer} 事件。
|
||||
*/
|
||||
function transfer(address to, uint256 value) external returns (bool);
|
||||
|
||||
/**
|
||||
* @dev Returns the remaining number of tokens that `spender` will be
|
||||
* allowed to spend on behalf of `owner` through {transferFrom}. This is
|
||||
* zero by default.
|
||||
* @dev 返回 `spender` 将被允许通过 {transferFrom} 代表 `owner` 花费的剩余代币数量。
|
||||
* 默认情况下为零。
|
||||
*
|
||||
* This value changes when {approve} or {transferFrom} are called.
|
||||
* 当调用 {approve} 或 {transferFrom} 时,此值会发生变化。
|
||||
*/
|
||||
function allowance(address owner, address spender) external view returns (uint256);
|
||||
|
||||
/**
|
||||
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
|
||||
* caller's tokens.
|
||||
* @dev 将 `value` 数量的代币设置为 `spender` 对调用者代币的授权额度。
|
||||
*
|
||||
* Returns a boolean value indicating whether the operation succeeded.
|
||||
* 返回一个布尔值,指示操作是否成功。
|
||||
*
|
||||
* IMPORTANT: Beware that changing an allowance with this method brings the risk
|
||||
* that someone may use both the old and the new allowance by unfortunate
|
||||
* transaction ordering. One possible solution to mitigate this race
|
||||
* condition is to first reduce the spender's allowance to 0 and set the
|
||||
* desired value afterwards:
|
||||
* 重要:请注意,使用此方法更改授权额度会带来风险,即有人可能会因为不幸的交易顺序
|
||||
* 同时使用旧的和新的授权额度。缓解这种竞争条件的一种可能解决方案是首先将 spender 的
|
||||
* 授权额度减少到 0,然后再设置所需的值:
|
||||
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
|
||||
*
|
||||
* Emits an {Approval} event.
|
||||
* 发出 {Approval} 事件。
|
||||
*/
|
||||
function approve(address spender, uint256 value) external returns (bool);
|
||||
|
||||
/**
|
||||
* @dev Moves a `value` amount of tokens from `from` to `to` using the
|
||||
* allowance mechanism. `value` is then deducted from the caller's
|
||||
* allowance.
|
||||
* @dev 使用授权机制从 `from` 向 `to` 转移 `value` 数量的代币。
|
||||
* 然后从调用者的授权额度中扣除 `value`。
|
||||
*
|
||||
* Returns a boolean value indicating whether the operation succeeded.
|
||||
* 返回一个布尔值,指示操作是否成功。
|
||||
*
|
||||
* Emits a {Transfer} event.
|
||||
* 发出 {Transfer} 事件。
|
||||
*/
|
||||
function transferFrom(address from, address to, uint256 value) external returns (bool);
|
||||
}
|
||||
|
||||
@ -6,29 +6,27 @@ pragma solidity ^0.8.20;
|
||||
import {Errors} from "./Errors.sol";
|
||||
|
||||
/**
|
||||
* @dev Collection of functions related to the address type
|
||||
* @dev 与地址类型相关的函数集合
|
||||
*/
|
||||
library Address {
|
||||
/**
|
||||
* @dev There's no code at `target` (it is not a contract).
|
||||
* @dev 在 `target` 处没有代码(它不是一个合约)。
|
||||
*/
|
||||
error AddressEmptyCode(address target);
|
||||
|
||||
/**
|
||||
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
|
||||
* `recipient`, forwarding all available gas and reverting on errors.
|
||||
* @dev Solidity 的 `transfer` 的替代品:向 `recipient` 发送 `amount` wei,
|
||||
* 转发所有可用的 gas 并在出错时回退。
|
||||
*
|
||||
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
|
||||
* of certain opcodes, possibly making contracts go over the 2300 gas limit
|
||||
* imposed by `transfer`, making them unable to receive funds via
|
||||
* `transfer`. {sendValue} removes this limitation.
|
||||
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] 增加了某些操作码的 gas 成本,
|
||||
* 可能使合约超过 `transfer` 施加的 2300 gas 限制,使它们无法通过 `transfer` 接收资金。
|
||||
* {sendValue} 移除了这个限制。
|
||||
*
|
||||
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
|
||||
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[了解更多]。
|
||||
*
|
||||
* IMPORTANT: because control is transferred to `recipient`, care must be
|
||||
* taken to not create reentrancy vulnerabilities. Consider using
|
||||
* {ReentrancyGuard} or the
|
||||
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
|
||||
* 重要:因为控制权转移到 `recipient`,必须注意不要创建重入漏洞。
|
||||
* 考虑使用 {ReentrancyGuard} 或
|
||||
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[检查-效果-交互模式]。
|
||||
*/
|
||||
function sendValue(address payable recipient, uint256 amount) internal {
|
||||
if (address(this).balance < amount) {
|
||||
@ -42,22 +40,19 @@ library Address {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Performs a Solidity function call using a low level `call`. A
|
||||
* plain `call` is an unsafe replacement for a function call: use this
|
||||
* function instead.
|
||||
* @dev 使用低级 `call` 执行 Solidity 函数调用。普通的 `call` 是函数调用的不安全替代品:
|
||||
* 请使用此函数替代。
|
||||
*
|
||||
* If `target` reverts with a revert reason or custom error, it is bubbled
|
||||
* up by this function (like regular Solidity function calls). However, if
|
||||
* the call reverted with no returned reason, this function reverts with a
|
||||
* {Errors.FailedCall} error.
|
||||
* 如果 `target` 使用回退原因或自定义错误回退,则此函数会将其冒泡(如常规 Solidity 函数调用)。
|
||||
* 但是,如果调用没有返回原因就回退,则此函数会使用 {Errors.FailedCall} 错误回退。
|
||||
*
|
||||
* Returns the raw returned data. To convert to the expected return value,
|
||||
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
|
||||
* 返回原始返回数据。要转换为期望的返回值,请使用
|
||||
* https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]。
|
||||
*
|
||||
* Requirements:
|
||||
* 要求:
|
||||
*
|
||||
* - `target` must be a contract.
|
||||
* - calling `target` with `data` must not revert.
|
||||
* - `target` 必须是一个合约。
|
||||
* - 使用 `data` 调用 `target` 不能回退。
|
||||
*/
|
||||
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
|
||||
return functionCallWithValue(target, data, 0);
|
||||
|
||||
@ -6,7 +6,7 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const INSTANCES = {
|
||||
// ERC-4337 Entrypoints
|
||||
// ERC-4337 入口点
|
||||
entrypoint: {
|
||||
v07: {
|
||||
address: '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
|
||||
@ -32,15 +32,15 @@ const INSTANCES = {
|
||||
},
|
||||
},
|
||||
deployer: {
|
||||
// Arachnid's deterministic deployment proxy
|
||||
// See: https://github.com/Arachnid/deterministic-deployment-proxy/tree/master
|
||||
// Arachnid 的确定性部署代理
|
||||
// 参见:https://github.com/Arachnid/deterministic-deployment-proxy/tree/master
|
||||
arachnid: {
|
||||
address: '0x4e59b44847b379578588920cA78FbF26c0B4956C',
|
||||
abi: [],
|
||||
bytecode:
|
||||
'0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3',
|
||||
},
|
||||
// Micah's deployer
|
||||
// Micah 的部署器
|
||||
micah: {
|
||||
address: '0x7A0D94F55792C434d74a40883C6ed8545E406D12',
|
||||
abi: [],
|
||||
|
||||
@ -1,15 +1,12 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// This script snapshots the bytecode and ABI for the `hardhat/common-contracts.js` script.
|
||||
// - Bytecode is fetched directly from the blockchain by querying the provided client endpoint. If no endpoint is
|
||||
// provided, ethers default provider is used instead.
|
||||
// - ABI is fetched from etherscan's API using the provided etherscan API key. If no API key is provided, ABI will not
|
||||
// be fetched and saved.
|
||||
// 此脚本为 `hardhat/common-contracts.js` 脚本快照字节码和 ABI。
|
||||
// - 字节码通过查询提供的客户端端点直接从区块链获取。如果没有提供端点,则使用 ethers 默认提供者。
|
||||
// - ABI 使用提供的 etherscan API 密钥从 etherscan 的 API 获取。如果没有提供 API 密钥,则不会获取和保存 ABI。
|
||||
//
|
||||
// The produced artifacts are stored in the `output` folder ('test/bin' by default). For each contract, two files are
|
||||
// produced:
|
||||
// - `<name>.bytecode` containing the contract bytecode (in binary encoding)
|
||||
// - `<name>.abi` containing the ABI (in utf-8 encoding)
|
||||
// 生成的工件存储在 `output` 文件夹中(默认为 'test/bin')。对于每个合约,生成两个文件:
|
||||
// - `<name>.bytecode` 包含合约字节码(二进制编码)
|
||||
// - `<name>.abi` 包含 ABI(utf-8 编码)
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
@ -24,7 +21,7 @@ const { argv } = require('yargs/yargs')(hideBin(process.argv))
|
||||
etherscan: { type: 'string' },
|
||||
});
|
||||
|
||||
// List of contract names and addresses to fetch
|
||||
// 要获取的合约名称和地址列表
|
||||
const config = {
|
||||
EntryPoint070: '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
|
||||
SenderCreator070: '0xEFC2c1444eBCC4Db75e7613d20C6a62fF67A167C',
|
||||
|
||||
@ -30,10 +30,10 @@ function generateFromTemplate(file, template, outputPrefix = '', lint = false) {
|
||||
lint && cp.execFileSync('prettier', ['--write', output]);
|
||||
}
|
||||
|
||||
// Some templates needs to go through the linter after generation
|
||||
// 一些模板在生成后需要通过 linter 检查
|
||||
const needsLinter = ['utils/structs/EnumerableMap.sol'];
|
||||
|
||||
// Contracts
|
||||
// 合约
|
||||
for (const [file, template] of Object.entries({
|
||||
'utils/cryptography/MerkleProof.sol': './templates/MerkleProof.js',
|
||||
'utils/math/SafeCast.sol': './templates/SafeCast.js',
|
||||
@ -51,7 +51,7 @@ for (const [file, template] of Object.entries({
|
||||
generateFromTemplate(file, template, './contracts/', needsLinter.includes(file));
|
||||
}
|
||||
|
||||
// Tests
|
||||
// 测试
|
||||
for (const [file, template] of Object.entries({
|
||||
'utils/structs/Checkpoints.t.sol': './templates/Checkpoints.t.js',
|
||||
'utils/Packing.t.sol': './templates/Packing.t.js',
|
||||
|
||||
Reference in New Issue
Block a user