We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
在Solidity中,Ownable 合约是一种设计模式,用于管理合约的所有权。它通常提供了一些基础功能,如只允许合约所有者执行某些操作,转移合约所有权等;这种权限管理合约在以太坊主网或者其他链的主网上经常会看到。
Ownable
我们需要声明一个叫做 Ownable 的合约,这个合约中,有一个状态变量,表示的是合约的所有权属于谁。这个状态变量会在合约部署的时候在构造函数中初始化, 我们并不希望外部直接访问这个变量,所以使用 private修饰符。
private
为了逻辑复用考虑,我们需要封装一个函数,作用是转移相关权限,这个函数在初始化的时候调用,在后续需要更改合约所有权的时候也需要调用。
基于上面的基础描述,我们用代码实现一下:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; contract Ownable { address private _owner; constructor() { _transferOwnership(msg.sender); } function _transferOwnership(address newOwner) internal { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
从上面的实现可以看到,_transferOwnership 函数被 internal 修饰,意思是不愿意被外部调用。我们需要封装一个外部可访问的函数,来调用这个内部函数, 并且,我们还需要设计一个 modifier 来限制只有合约的权限管理者才能调用这个方法。
_transferOwnership
internal
modifier
基于这个思路,我们补充完善一下代码:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; contract Ownable { address private _owner; constructor() { _transferOwnership(msg.sender); } modifier onlyOwner() { require(owner() == msg.sender, "Ownable: caller is not the owner"); _; } function transferOwnership(address newOwner) public onlyOwner { // 这里需要注意,新的地址不能是0地址,否则权限就会被永久锁死了 require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } function _transferOwnership(address newOwner) internal { address oldOwner = _owner; _owner = newOwner; } }
在实际的使用场景中,会有一个需求,就是合约的所有者主动放弃所有权,如果想要实现这个功能,直接将自己的所有权转让给0地址。基于这个思路,我们可以设计一个 renounceOwnership 方法。
renounceOwnership
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; contract Ownable { address private _owner; constructor() { _transferOwnership(msg.sender); } modifier onlyOwner() { require(owner() == msg.sender, "Ownable: caller is not the owner"); _; } function renounceOwnership() public onlyOwner { _transferOwnership(address(0)); } function transferOwnership(address newOwner) public onlyOwner { // 这里需要注意,新的地址不能是0地址,否则权限就会被永久锁死了 require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } function _transferOwnership(address newOwner) internal { address oldOwner = _owner; _owner = newOwner; } }
可以看到 renounceOwnership 也是只有合约所有者才可以调用,并且直接调用底层的 _transferOwnership 函数,绕过了0地址的检查。
最后,我们再提供一个函数来查询最新的合约所有者的地址, 还需要添加一个事件,当合约所有者权限更改的时候,我们抛出一个事件。这样一个完整的合约就实现了。
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; /** * @title Ownable * @dev Ownable合约有一个owner地址类型的状态变量,提供了基础的权限管理函数 */ contract Ownable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev 初始化,将合约的部署者设置为合约的拥有者 */ constructor() { _transferOwnership(msg.sender); } /** * @dev 返回当前的合约所有者 */ function owner() public view returns (address) { return _owner; } /** * @dev 不是合约拥有者调用的时候抛出异常 */ modifier onlyOwner() { require(owner() == msg.sender, "Ownable: caller is not the owner"); _; } /** * @dev 当前所有者可以调用这个函数放弃所有权,这会将合约的所有者设置为零地址(`address(0)`) */ function renounceOwnership() public onlyOwner { _transferOwnership(address(0)); } /** * @dev 转移合约拥有权到一个新的地址,只能被合约拥有者调用 */ function transferOwnership(address newOwner) public onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * 内部函数,没有权限校验 */ function _transferOwnership(address newOwner) internal { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
_owner
OwnershipTransferred
onlyOwner
owner
address(0)
transferOwnership
我们熟知的OpenZeppelin提供了最广泛使用和高度可信赖的权限管理工具,包括 Ownable 和 AccessControl。可以帮助你轻松实现智能合约中的角色和权限管理。
AccessControl
此外,其他一些库如ConsenSys和DappSys也提供了有用的权限管理解决方案,但它们的使用范围和知名度不如OpenZeppelin。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
基本概念
在Solidity中,
Ownable
合约是一种设计模式,用于管理合约的所有权。它通常提供了一些基础功能,如只允许合约所有者执行某些操作,转移合约所有权等;这种权限管理合约在以太坊主网或者其他链的主网上经常会看到。实现思路、步骤
我们需要声明一个叫做
Ownable
的合约,这个合约中,有一个状态变量,表示的是合约的所有权属于谁。这个状态变量会在合约部署的时候在构造函数中初始化, 我们并不希望外部直接访问这个变量,所以使用private
修饰符。为了逻辑复用考虑,我们需要封装一个函数,作用是转移相关权限,这个函数在初始化的时候调用,在后续需要更改合约所有权的时候也需要调用。
基于上面的基础描述,我们用代码实现一下:
从上面的实现可以看到,
_transferOwnership
函数被internal
修饰,意思是不愿意被外部调用。我们需要封装一个外部可访问的函数,来调用这个内部函数, 并且,我们还需要设计一个modifier
来限制只有合约的权限管理者才能调用这个方法。基于这个思路,我们补充完善一下代码:
在实际的使用场景中,会有一个需求,就是合约的所有者主动放弃所有权,如果想要实现这个功能,直接将自己的所有权转让给0地址。基于这个思路,我们可以设计一个
renounceOwnership
方法。可以看到
renounceOwnership
也是只有合约所有者才可以调用,并且直接调用底层的_transferOwnership
函数,绕过了0地址的检查。最后,我们再提供一个函数来查询最新的合约所有者的地址, 还需要添加一个事件,当合约所有者权限更改的时候,我们抛出一个事件。这样一个完整的合约就实现了。
完整代码示例:
代码说明
_owner
存储当前合约的所有者地址。OwnershipTransferred
事件,当所有权转移时,会记录之前的所有者和新的所有者。onlyOwner
修饰符,用于限制只有当前合约的所有者可以调用某些函数。owner
函数,返回当前所有者的地址。renounceOwnership
函数,当前所有者可以调用这个函数放弃所有权,这会将合约的所有者设置为零地址(address(0)
)。transferOwnership
函数,当前所有者可以将合约的所有权转移给新的地址。新地址不能是零地址。_transferOwnership
内部函数执行实际的所有权转移操作,并触发所有权转移事件。总结
我们熟知的OpenZeppelin提供了最广泛使用和高度可信赖的权限管理工具,包括
Ownable
和AccessControl
。可以帮助你轻松实现智能合约中的角色和权限管理。此外,其他一些库如ConsenSys和DappSys也提供了有用的权限管理解决方案,但它们的使用范围和知名度不如OpenZeppelin。
The text was updated successfully, but these errors were encountered: