LOADING

加载过慢请开启缓存 浏览器默认开启

Code review: Openzeppelin-IAccessControlDefaultAdminRules

2023/6/26 Solidity Coding

概述:

该合约代码定义了一个名为IAccessControlDefaultAdminRules的接口,用于管理访问控制和默认管理员角色的转移。它提供了以下功能:

  1. 管理默认管理员角色的转移:

    • 可以启动默认管理员角色的转移,并设置新的管理员地址和接受计划。
    • 可以取消尚未接受的管理员转移。
    • 可以完成管理员转移,将DEFAULT_ADMIN_ROLE授予调用者,并从之前的持有者中撤销该角色。
  2. 管理默认管理员角色转移的延迟:

    • 可以设置默认管理员转移的延迟时间。
    • 可以取消预定的延迟更改。
    • 可以查询当前的默认管理员转移延迟时间和预定的延迟更改。
  3. 提供事件以便监控默认管理员角色和延迟更改的状态:

    • 可以监听默认管理员转移和延迟更改的开始、取消和完成事件。

这个接口为访问控制合约提供了一些附加的管理功能,使得在系统中转移默认管理员角色更加灵活和可控。

完整代码:

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.9.0 (access/IAccessControlDefaultAdminRules.sol)

pragma solidity ^0.8.0;

import "./IAccessControl.sol";

/**
 * @dev External interface of AccessControlDefaultAdminRules declared to support ERC165 detection.
 *
 * _Available since v4.9._
 */
interface IAccessControlDefaultAdminRules is IAccessControl {
    /**
     * @dev Emitted when a {defaultAdmin} transfer is started, setting `newAdmin` as the next
     * address to become the {defaultAdmin} by calling {acceptDefaultAdminTransfer} only after `acceptSchedule`
     * passes.
     */
    event DefaultAdminTransferScheduled(address indexed newAdmin, uint48 acceptSchedule);

    /**
     * @dev Emitted when a {pendingDefaultAdmin} is reset if it was never accepted, regardless of its schedule.
     */
    event DefaultAdminTransferCanceled();

    /**
     * @dev Emitted when a {defaultAdminDelay} change is started, setting `newDelay` as the next
     * delay to be applied between default admin transfer after `effectSchedule` has passed.
     */
    event DefaultAdminDelayChangeScheduled(uint48 newDelay, uint48 effectSchedule);

    /**
     * @dev Emitted when a {pendingDefaultAdminDelay} is reset if its schedule didn't pass.
     */
    event DefaultAdminDelayChangeCanceled();

    /**
     * @dev Returns the address of the current `DEFAULT_ADMIN_ROLE` holder.
     */
    function defaultAdmin() external view returns (address);

    /**
     * @dev Returns a tuple of a `newAdmin` and an accept schedule.
     *
     * After the `schedule` passes, the `newAdmin` will be able to accept the {defaultAdmin} role
     * by calling {acceptDefaultAdminTransfer}, completing the role transfer.
     *
     * A zero value only in `acceptSchedule` indicates no pending admin transfer.
     *
     * NOTE: A zero address `newAdmin` means that {defaultAdmin} is being renounced.
     */
    function pendingDefaultAdmin() external view returns (address newAdmin, uint48 acceptSchedule);

    /**
     * @dev Returns the delay required to schedule the acceptance of a {defaultAdmin} transfer started.
     *
     * This delay will be added to the current timestamp when calling {beginDefaultAdminTransfer} to set
     * the acceptance schedule.
     *
     * NOTE: If a delay change has been scheduled, it will take effect as soon as the schedule passes, making this
     * function returns the new delay. See {changeDefaultAdminDelay}.
     */
    function defaultAdminDelay() external view returns (uint48);

    /**
     * @dev Returns a tuple of `newDelay` and an effect schedule.
     *
     * After the `schedule` passes, the `newDelay` will get into effect immediately for every
     * new {defaultAdmin} transfer started with {beginDefaultAdminTransfer}.
     *
     * A zero value only in `effectSchedule` indicates no pending delay change.
     *
     * NOTE: A zero value only for `newDelay` means that the next {defaultAdminDelay}
     * will be zero after the effect schedule.
     */
    function pendingDefaultAdminDelay() external view returns (uint48 newDelay, uint48 effectSchedule);

    /**
     * @dev Starts a {defaultAdmin} transfer by setting a {pendingDefaultAdmin} scheduled for acceptance
     * after the current timestamp plus a {defaultAdminDelay}.
     *
     * Requirements:
     *
     * - Only can be called by the current {defaultAdmin}.
     *
     * Emits a DefaultAdminRoleChangeStarted event.
     */
    function beginDefaultAdminTransfer(address newAdmin) external;

    /**
     * @dev Cancels a {defaultAdmin} transfer previously started with {beginDefaultAdminTransfer}.
     *
     * A {pendingDefaultAdmin} not yet accepted can also be cancelled with this function.
     *
     * Requirements:
     *
     * - Only can be called by the current {defaultAdmin}.
     *
     * May emit a DefaultAdminTransferCanceled event.
     */
    function cancelDefaultAdminTransfer() external;

    /**
     * @dev Completes a {defaultAdmin} transfer previously started with {beginDefaultAdminTransfer}.
     *
     * After calling the function:
     *
     * - `DEFAULT_ADMIN_ROLE` should be granted to the caller.
     * - `DEFAULT_ADMIN_ROLE` should be revoked from the previous holder.
     * - {pendingDefaultAdmin} should be reset to zero values.
     *
     * Requirements:
     *
     * - Only can be called by the {pendingDefaultAdmin}'s `newAdmin`.
     * - The {pendingDefaultAdmin}'s `acceptSchedule` should've passed.
     */
    function acceptDefaultAdminTransfer() external;

    /**
     * @dev Initiates a {defaultAdminDelay} update by setting a {pendingDefaultAdminDelay} scheduled for getting
     * into effect after the current timestamp plus a {defaultAdminDelay}.
     *
     * This function guarantees that any call to {beginDefaultAdminTransfer} done between the timestamp this
     * method is called and the {pendingDefaultAdminDelay} effect schedule will use the current {defaultAdminDelay}
     * set before calling.
     *
     * The {pendingDefaultAdminDelay}'s effect schedule is defined in a way that waiting until the schedule and then
     * calling {beginDefaultAdminTransfer} with the new delay will take at least the same as another {defaultAdmin}
     * complete transfer (including acceptance).
     *
     * The schedule is designed for two scenarios:
     *
     * - When the delay is changed for a larger one the schedule is `block.timestamp + newDelay` capped by
     * {defaultAdminDelayIncreaseWait}.
     * - When the delay is changed for a shorter one, the schedule is `block.timestamp + (current delay - new delay)`.
     *
     * A {pendingDefaultAdminDelay} that never got into effect will be canceled in favor of a new scheduled change.
     *
     * Requirements:
     *
     * - Only can be called by the current {defaultAdmin}.
     *
     * Emits a DefaultAdminDelayChangeScheduled event and may emit a DefaultAdminDelayChangeCanceled event.
     */
    function changeDefaultAdminDelay(uint48 newDelay) external;

    /**
     * @dev Cancels a scheduled {defaultAdminDelay} change.
     *
     * Requirements:
     *
     * - Only can be called by the current {defaultAdmin}.
     *
     * May emit a DefaultAdminDelayChangeCanceled event.
     */
    function rollbackDefaultAdminDelay() external;

    /**
     * @dev Maximum time in seconds for an increase to {defaultAdminDelay} (that is scheduled using {changeDefaultAdminDelay})
     * to take effect. Default to 5 days.
     *
     * When the {defaultAdminDelay} is scheduled to be increased, it goes into effect after the new delay has passed with
     * the purpose of giving enough time for reverting any accidental change (i.e. using milliseconds instead of seconds)
     * that may lock the contract. However, to avoid excessive schedules, the wait is capped by this function and it can
     * be overrode for a custom {defaultAdminDelay} increase scheduling.
     *
     * IMPORTANT: Make sure to add a reasonable amount of time while overriding this value, otherwise,
     * there's a risk of setting a high new delay that goes into effect almost immediately without the
     * possibility of human intervention in the case of an input error (eg. set milliseconds instead of seconds).
     */
    function defaultAdminDelayIncreaseWait() external view returns (uint48);
}

代码分析:

interface IAccessControlDefaultAdminRules is IAccessControl {

该行代码定义了一个名为IAccessControlDefaultAdminRules的接口,并且该接口继承自IAccessControl接口。接口的作用是扩展和增强访问控制功能,并提供默认管理员规则的管理功能。

继承自IAccessControl接口意味着IAccessControlDefaultAdminRules接口包含了IAccessControl接口中定义的所有函数和事件,并且在此基础上添加了额外的函数和事件。

通过继承自IAccessControl接口,IAccessControlDefaultAdminRules接口可以使用和操作访问控制相关的函数,如授予角色、撤销角色、检查角色授权等。同时,通过添加额外的函数和事件,IAccessControlDefaultAdminRules接口还提供了管理默认管理员规则的功能。

这样的设计使得IAccessControlDefaultAdminRules接口成为一个更具功能性的接口,继承了基本的访问控制功能,并增加了默认管理员规则的管理功能,使得访问控制合约更加灵活和可扩展。

event DefaultAdminTransferScheduled(address indexed newAdmin, uint48 acceptSchedule);

该代码段定义了一个名为DefaultAdminTransferScheduled的事件。当执行默认管理员角色转移,并设置新的管理员地址和接受计划时,会触发此事件。

该事件具有两个参数:

  1. address indexed newAdmin:新的管理员地址。当默认管理员角色转移成功时,该地址将成为新的默认管理员。

  2. uint48 acceptSchedule:接受计划。它表示默认管理员角色转移的接受时间。在接受计划指定的时间之后,新的管理员可以通过调用接口中的acceptDefaultAdminTransfer函数来接受默认管理员角色。

通过触发DefaultAdminTransferScheduled事件,合约可以通知其他相关方关于默认管理员角色转移的计划和新管理员的地址。这样,其他方可以监听该事件并根据需要执行相应的操作,例如更新用户界面或执行其他逻辑

event DefaultAdminTransferCanceled();

这行代码定义了一个事件(event)DefaultAdminTransferCanceled。事件是合约中发生的某种事情或状态变化的通知机制,它允许其他合约或外部应用程序监听和响应这些事件。

DefaultAdminTransferCanceled事件在以下情况下被触发:

  • 当默认管理员角色的转移被取消时。

该事件的目的是向合约的其他部分或外部应用程序传达一个重要的信息,即默认管理员角色的转移已被取消。这可以帮助其他合约或应用程序及时获得有关默认管理员角色转移状态的更新。

当这个事件被触发时,可以通过监听合约事件并编写相应的事件处理程序来执行特定的逻辑或操作。这样可以使合约的其他部分或外部应用程序能够根据转移取消的情况采取相应的行动。

event DefaultAdminDelayChangeScheduled(uint48 newDelay, uint48 effectSchedule);

该代码定义了一个事件(event)名为DefaultAdminDelayChangeScheduled。该事件在默认管理员延迟更改被调度时触发。

参数说明:

  • newDelay:新的延迟时间,以uint48类型表示。
  • effectSchedule:生效计划,以uint48类型表示。

解释代码功能:
该事件的目的是通知合约的事件监听者(包括其他合约或外部应用程序)默认管理员延迟更改已被调度。当调用changeDefaultAdminDelay函数更改默认管理员的延迟时间时,将触发此事件。

具体流程如下:

  1. 在调用changeDefaultAdminDelay函数时,设置了新的延迟时间newDelay。
  2. 根据调用changeDefaultAdminDelay函数的当前时间戳,计算并设置了生效计划effectSchedule。
  3. 事件DefaultAdminDelayChangeScheduled被触发,将新的延迟时间newDelay和生效计划effectSchedule作为参数传递给事件的监听者。
  4. 外部应用程序或其他合约可以监听该事件,以便在默认管理员延迟更改被调度时执行相应的操作。

通过该事件,合约的用户可以了解到默认管理员延迟更改的调度情况,从而可以做出相应的处理或决策。

event DefaultAdminDelayChangeCanceled();

该代码定义了一个名为DefaultAdminDelayChangeCanceled的事件。

DefaultAdminDelayChangeCanceled事件在以下情况下被触发:

  • 当之前计划中的默认管理员延迟更改被取消时。

该事件的目的是通知合约的使用者或其他监听者,有一个预定的默认管理员延迟更改被取消了。

这个事件的定义不提供具体的参数,因此它只是一个简单的通知事件,用于记录和跟踪默认管理员延迟更改的取消操作。

代码功能:

  • DefaultAdminDelayChangeCanceled事件的存在提供了一种机制,可以在默认管理员延迟更改被取消时发出通知,以便其他相关的业务逻辑或用户界面能够感知到这种变化并采取相应的行动。
function defaultAdmin() external view returns (address);

该代码片段是一个函数定义,名为defaultAdmin,是一个公共的视图函数(external view)。该函数不接收任何参数,返回一个地址类型(address)的值。

函数的作用是返回当前合约中的默认管理员(defaultAdmin)地址。默认管理员是具有特殊权限的角色,通常用于管理合约的操作和权限控制。

由于该函数是一个视图函数(view),它不修改合约状态,因此调用该函数不会消耗任何以太币。它只返回存储在合约中的默认管理员地址,并且其他合约或外部调用者可以通过调用该函数来获取该地址。

通过提供这个函数,合约的用户和其他合约可以方便地查询默认管理员地址,以便根据需要进行相应的操作和权限验证。

function pendingDefaultAdmin() external view returns (address newAdmin, uint48 acceptSchedule);

该函数是IAccessControlDefaultAdminRules接口中的一个函数。它是一个公共的视图函数(external view),用于查询当前挂起的默认管理员转移信息。

函数返回一个元组,包含两个值:

  1. newAdmin:地址类型。表示即将成为默认管理员的新管理员地址。

    • 如果newAdmin为零地址,则表示当前正在放弃默认管理员角色。
  2. acceptSchedule:uint48类型。表示接受默认管理员角色转移的计划时间。

    • 如果acceptSchedule为零,则表示当前没有挂起的管理员转移。

这个函数的作用是允许外部调用者查询当前是否有挂起的默认管理员转移,并获取相关的信息。通过调用这个函数,可以了解下一个默认管理员的地址和接受转移的计划时间。

function defaultAdminDelay() external view returns (uint48);

该代码定义了一个名为defaultAdminDelay的公共视图函数。该函数没有参数,并返回一个uint48类型的值。

函数的功能是查询当前默认管理员转移的延迟时间。

由于函数标记为view,表示该函数只读取状态而不修改合约状态。因此,它可以在不消耗任何燃料费用的情况下被其他合约或外部调用者调用。

调用该函数将返回当前默认管理员转移的延迟时间,以uint48整数的形式表示。

需要注意的是,该函数仅返回当前的默认管理员转移延迟时间,并不包括任何已计划或挂起的延迟更改。如需获取挂起的延迟更改信息,可以使用其他相关函数,例如pendingDefaultAdminDelay

function pendingDefaultAdminDelay() external view returns (uint48 newDelay, uint48 effectSchedule);

该函数是接口IAccessControlDefaultAdminRules中的一个函数,用于查询当前的待定默认管理员延迟更改。

函数定义为function pendingDefaultAdminDelay() external view returns (uint48 newDelay, uint48 effectSchedule);

该函数具体功能如下:

  • 该函数是一个视图函数,不会修改合约状态,可以在任何时候调用。
  • 该函数返回一个元组,包含两个返回值:
    • newDelay:表示待定的新延迟值。
    • effectSchedule:表示新延迟值生效的计划时间。

函数的作用是查询当前设置但尚未生效的默认管理员延迟更改。通常,当调用changeDefaultAdminDelay函数时,会设置一个新的延迟值,并计划在一定时间后生效。该函数可以用来获取这个待定的新延迟值以及它预计生效的计划时间。

通过调用该函数,可以了解当前是否存在待定的默认管理员延迟更改,以及新的延迟值和生效计划的具体数值。这对于系统管理员或其他合约可以在合适的时机查询并了解当前的默认管理员延迟更改状态非常有用。

function beginDefaultAdminTransfer(address newAdmin) external;

函数beginDefaultAdminTransferIAccessControlDefaultAdminRules接口中的一个函数,用于启动默认管理员角色的转移过程。

该函数接受一个参数newAdmin,表示新的管理员地址。调用该函数后,将启动一个默认管理员角色的转移过程,并设置newAdmin作为下一个将接受默认管理员角色的地址。

转移过程的具体流程如下:

  1. 调用beginDefaultAdminTransfer函数时,必须由当前的默认管理员调用。
  2. 调用成功后,会触发一个DefaultAdminTransferScheduled事件,其中包含newAdmin和接受计划。
  3. 在接受计划指定的时间之后,newAdmin可以调用acceptDefaultAdminTransfer函数来接受默认管理员角色。

通过调用beginDefaultAdminTransfer函数,可以启动一个默认管理员角色的转移过程,将默认管理员角色转移到指定的新管理员地址上。这个功能允许在系统中动态更改默认管理员角色,提供了灵活的访问控制管理能力。

function cancelDefaultAdminTransfer() external;

该代码定义了一个名为cancelDefaultAdminTransfer的外部函数。下面是对该函数功能的详细解释:

函数功能: cancelDefaultAdminTransfer函数用于取消之前启动的默认管理员角色转移。当调用者调用beginDefaultAdminTransfer函数启动默认管理员角色转移后,如果转移尚未被接受,即pendingDefaultAdmin存在但未被接受,可以使用cancelDefaultAdminTransfer函数取消该转移。

函数访问修饰符:

  • external:表明该函数只能从合约外部调用。

函数参数:
该函数没有参数。

函数行为:
当调用者调用cancelDefaultAdminTransfer函数时,以下条件必须满足:

  • 调用者必须是当前的默认管理员(DEFAULT_ADMIN_ROLE的持有者)。

如果满足以上条件,函数将执行以下操作:

  • 取消之前启动的默认管理员角色转移,无论转移是否已经被接受。
  • 如果存在尚未接受的pendingDefaultAdmin,将其重置为零值。

函数事件:
该函数可能触发以下事件:

  • DefaultAdminTransferCanceled:当成功取消默认管理员角色转移时,可能会触发该事件。

注意事项:

  • 只有当前的默认管理员才能调用cancelDefaultAdminTransfer函数取消默认管理员角色转移。
  • 取消默认管理员角色转移后,需要重新调用beginDefaultAdminTransfer函数启动新的转移过程,如果需要更改默认管理员。
function acceptDefaultAdminTransfer() external;

函数acceptDefaultAdminTransfer是一个公开的外部函数。以下是对该函数的功能解释:

该函数用于完成默认管理员角色的转移。只有在调用此函数后,DEFAULT_ADMIN_ROLE才会被授予调用者,并且之前的默认管理员将失去该角色。

调用该函数的要求如下:

  • 只能由pendingDefaultAdmin(即被指定为新默认管理员的地址)的newAdmin调用。
  • pendingDefaultAdminacceptSchedule(接受计划)应该已经过去,即到达或超过了指定的时间。

当调用此函数后,将会发生以下情况:

  • DEFAULT_ADMIN_ROLE将授予调用者,使其成为新的默认管理员。
  • 之前的默认管理员将被撤销DEFAULT_ADMIN_ROLE
  • pendingDefaultAdmin将被重置为零值,即新的默认管理员转移完成。

该函数的作用是确保只有被指定为新默认管理员的地址可以最终接受并成为默认管理员角色的持有者。这个函数的调用将完成默认管理员角色的转移过程,并确保只有授权的地址可以接受该角色。

请注意,调用该函数的合适时机是在pendingDefaultAdminacceptSchedule过去后。这可以通过与相应的事件和其他函数一起使用来实现更灵活的管理员角色转移逻辑。

function changeDefaultAdminDelay(uint48 newDelay) external;

该函数的功能是更改默认管理员转移的延迟时间。

参数newDelay是一个uint48类型的整数,表示新的延迟时间。该参数指定了在调用beginDefaultAdminTransfer函数启动默认管理员转移后,需要等待多长时间才能接受该转移。

以下是函数的详细解释:

  • 访问修饰符:external表示该函数只能从合约外部调用。

  • 函数名称:changeDefaultAdminDelay表示更改默认管理员转移延迟的函数。

  • 参数:newDelay是一个uint48类型的整数,表示新的延迟时间。它指定了在调用beginDefaultAdminTransfer函数启动默认管理员转移后,需要等待多长时间才能接受该转移。

  • 函数修饰符:无。

  • 函数操作:

    1. 只能由当前的默认管理员调用该函数。
    2. 当该函数被调用时,将设置一个预定的默认管理员延迟更改,该更改将在当前时间戳加上newDelay之后生效。
    3. 在设置预定延迟更改之前,该函数会先取消之前预定但尚未生效的延迟更改。
    4. 通过调用该函数,可以灵活地更改默认管理员转移的延迟时间,以适应特定需求和业务逻辑。
    5. 该函数会触发DefaultAdminDelayChangeScheduled事件,用于通知其他合约和外部观察者延迟更改的计划。
  • 注意事项:

    • 该函数只能由当前的默认管理员调用,确保只有管理员有权更改延迟时间。
    • 如果之前有预定但尚未生效的延迟更改,调用该函数将取消该预定更改,以确保只有最新的延迟更改生效。
    • 调用该函数后,新的延迟时间将在预定的时间到达后生效,并影响后续的默认管理员转移操作。

该函数的作用是允许当前默认管理员更改默认管理员转移的延迟时间,从而灵活地控制默认管理员角色的转移过程。

function rollbackDefaultAdminDelay() external;

函数rollbackDefaultAdminDelay()是一个公共外部函数。以下是对该函数的详细解释:

功能:
该函数用于取消预定的默认管理员延迟更改。如果在调用changeDefaultAdminDelay()函数后,但在预定的生效计划之前,需要取消延迟更改,则可以使用此函数进行操作。

访问修饰符:
该函数具有external修饰符,表示只能从合约外部调用该函数。

参数:
该函数没有任何参数。

事件:
该函数不会触发任何事件。

要求:

  • 只能由当前的默认管理员调用该函数。

作用:
当需要取消预定的默认管理员延迟更改时,可以调用此函数。通过调用changeDefaultAdminDelay()函数设置了一个新的延迟值,并在预定的生效计划之前,可以使用此函数取消该预定的更改。

使用此函数后,预定的默认管理员延迟更改将被取消,并且将维持当前的默认管理员延迟值。这可以确保在预定更改生效之前,不会对默认管理员延迟产生任何影响。

需要注意的是,只有当前的默认管理员才能调用该函数,以确保只有授权的管理员可以取消延迟更改。

总结: rollbackDefaultAdminDelay()函数用于取消预定的默认管理员延迟更改。通过调用该函数,可以确保在预定的生效计划之前,取消默认管理员延迟的更改,并维持当前的延迟值。只有当前的默认管理员可以调用该函数。

function defaultAdminDelayIncreaseWait() external view returns (uint48);

该代码段是一个公共函数,函数名为defaultAdminDelayIncreaseWait,返回类型为uint48

该函数用于获取默认管理员延迟增加的等待时间。默认管理员延迟增加的概念是在调用changeDefaultAdminDelay函数时,新的延迟时间将在一定时间后生效。这个等待时间是为了确保足够的时间来撤销任何意外更改,以避免意外将合约锁定。该等待时间有一个默认值,但可以根据需要进行重写。

该函数的作用是返回当前默认管理员延迟增加的等待时间。它是一个只读函数,不修改合约状态,并且可以通过外部调用进行查询。