本文详细介绍了Solidity中的布尔类型,包括其定义、使用、逻辑运算符(与、或、非)、短路求值特性、比较运算符以及在条件语句中的应用。此外,还探讨了布尔类型在权限控制、状态管理、功能开关和白名单/黑名单等实际应用场景,并提供了布尔值存储的Gas优化建议和练习。
布尔类型(Boolean)是编程中最基础的数据类型之一,只有两个值:true(真)和 false(假)。在智能合约中,布尔类型常用于条件判断、权限控制和状态标记。
在 Solidity 中,布尔类型用 bool 关键字表示:
pragma solidity ^0.8.0;
contract BooleanBasics {
bool public isActive = true;
bool public isPaused = false;
bool public isInitialized; // 默认值为 false
function setState(bool _active) public {
isActive = _active;
}
function getState() public view returns (bool) {
return isActive;
}
}
提示: 布尔变量的默认值是
false。如果声明一个布尔变量但不赋值,它会自动初始化为false。
Solidity 支持三种逻辑运算符:
当且仅当两边都为 true 时,结果才为 true。
pragma solidity ^0.8.0;
contract LogicalAnd {
function andOperation() public pure returns (bool) {
bool a = true;
bool b = false;
bool result1 = true && true; // true
bool result2 = true && false; // false
bool result3 = false && true; // false
bool result4 = false && false; // false
return a && b; // false
}
// 实际应用:同时满足多个条件
function canWithdraw(address user, uint amount) public view returns (bool) {
bool hasBalance = address(user).balance >= amount;
bool isNotPaused = true; // 假设合约未暂停
return hasBalance && isNotPaused;
}
}
只要有一边为 true,结果就为 true。
pragma solidity ^0.8.0;
contract LogicalOr {
function orOperation() public pure returns (bool) {
bool result1 = true || true; // true
bool result2 = true || false; // true
bool result3 = false || true; // true
bool result4 = false || false; // false
return result1;
}
// 实际应用:满足任一条件即可
function hasPermission(address user, address owner, address admin)
public
pure
returns (bool)
{
return user == owner || user == admin;
}
}
取反操作,true 变 false,false 变 true。
pragma solidity ^0.8.0;
contract LogicalNot {
bool public isLocked = false;
function notOperation() public pure returns (bool) {
bool a = true;
bool b = false;
bool result1 = !a; // false
bool result2 = !b; // true
return !a;
}
// 实际应用:检查相反状态
function canAccess() public view returns (bool) {
return !isLocked; // 如果未锁定,则可以访问
}
}
| A | B | A && B |
|---|---|---|
| true | true | true |
| true | false | false |
| false | true | false |
| false | false | false |
| A | B | A \ | \ | B |
|---|---|---|---|---|
| true | true | true | ||
| true | false | true | ||
| false | true | true | ||
| false | false | false |
| A | !A |
|---|---|
| true | false |
| false | true |
Solidity 中的逻辑运算符支持短路求值(Short-circuit evaluation),这是一个重要的特性,既能提高效率,也能避免错误。
如果左边为 false,则右边的表达式不会执行。
pragma solidity ^0.8.0;
contract ShortCircuitAnd {
uint public counter = 0;
function incrementCounter() public returns (bool) {
counter++;
return true;
}
function testShortCircuit() public returns (uint) {
// 因为 false && ... 中,右边不会执行
// 所以 incrementCounter() 不会被调用
bool result = false && incrementCounter();
return counter; // 返回 0,counter 没有增加
}
function testNoShortCircuit() public returns (uint) {
// 因为 true && ... 中,需要判断右边
// 所以 incrementCounter() 会被调用
bool result = true && incrementCounter();
return counter; // 返回 1,counter 增加了
}
}
如果左边为 true,则右边的表达式不会执行。
pragma solidity ^0.8.0;
contract ShortCircuitOr {
uint public counter = 0;
function incrementCounter() public returns (bool) {
counter++;
return false;
}
function testShortCircuit() public returns (uint) {
// 因为 true || ... 中,右边不会执行
bool result = true || incrementCounter();
return counter; // 返回 0
}
function testNoShortCircuit() public returns (uint) {
// 因为 false || ... 中,需要判断右边
bool result = false || incrementCounter();
return counter; // 返回 1
}
}
短路求值可以避免错误并节省 Gas:
pragma solidity ^0.8.0;
contract ShortCircuitBenefit {
mapping(address => uint) public balances;
// 利用短路求值避免除零错误
function safeDivide(uint a, uint b) public pure returns (uint) {
// 如果 b == 0,右边的除法不会执行,避免了错误
return (b != 0) && (a / b > 10) ? a / b : 0;
}
// 利用短路求值节省 Gas
function canWithdraw(address user, uint amount) public view returns (bool) {
// 如果余额不足,就不需要执行后面的复杂检查
return balances[user] >= amount && complexCheck(user);
}
function complexCheck(address user) internal view returns (bool) {
// 假设这是一个复杂且消耗 Gas 的检查
return true;
}
}
Gas 优化: 在使用
&&时,把更可能为false的条件放在前面;使用||时,把更可能为true的条件放在前面。这样可以通过短路求值节省 Gas。
Solidity 支持六种比较运算符,比较的结果是布尔值:
pragma solidity ^0.8.0;
contract ComparisonOperators {
function compareNumbers(uint a, uint b) public pure returns (
bool isEqual,
bool isNotEqual,
bool isLess,
bool isLessOrEqual,
bool isGreater,
bool isGreaterOrEqual
) {
isEqual = (a == b); // 等于
isNotEqual = (a != b); // 不等于
isLess = (a < b); // 小于
isLessOrEqual = (a <= b); // 小于等于
isGreater = (a > b); // 大于
isGreaterOrEqual = (a >= b); // 大于等于
return (isEqual, isNotEqual, isLess, isLessOrEqual, isGreater, isGreaterOrEqual);
}
function compareAddresses(address a, address b) public pure returns (bool) {
return a == b; // 地址比较
}
function compareBools(bool a, bool b) public pure returns (bool) {
return a == b; // 布尔比较
}
}
布尔类型最常见的用途是在条件语句中进行判断。
pragma solidity ^0.8.0;
contract ConditionalStatements {
bool public isPaused = false;
function doSomething() public view returns (string memory) {
if (isPaused) {
return "Contract is paused";
} else {
return "Contract is active";
}
}
function checkAge(uint age) public pure returns (string memory) {
if (age < 18) {
return "Minor";
} else if (age < 65) {
return "Adult";
} else {
return "Senior";
}
}
}
pragma solidity ^0.8.0;
contract RequireExample {
address public owner;
bool public isPaused;
constructor() {
owner = msg.sender;
}
function restrictedFunction() public view {
require(!isPaused, "Contract is paused");
require(msg.sender == owner, "Not owner");
// 函数逻辑
}
}
pragma solidity ^0.8.0;
contract TernaryOperator {
function max(uint a, uint b) public pure returns (uint) {
return a > b ? a : b;
}
function getStatus(bool isActive) public pure returns (string memory) {
return isActive ? "Active" : "Inactive";
}
function abs(int x) public pure returns (int) {
return x >= 0 ? x : -x;
}
}
pragma solidity ^0.8.0;
contract AccessControl {
mapping(address => bool) public isAdmin;
mapping(address => bool) public isModerator;
modifier onlyAdmin() {
require(isAdmin[msg.sender], "Not an admin");
_;
}
modifier onlyAdminOrModerator() {
require(
isAdmin[msg.sender] || isModerator[msg.sender],
"No permission"
);
_;
}
function addAdmin(address user) public onlyAdmin {
isAdmin[user] = true;
}
function moderateContent() public onlyAdminOrModerator {
// 管理员或版主都可以执行
}
}
pragma solidity ^0.8.0;
contract StateManagement {
bool public isPaused;
bool public isInitialized;
bool public isFinalized;
function initialize() public {
require(!isInitialized, "Already initialized");
isInitialized = true;
// 初始化逻辑
}
function pause() public {
require(!isPaused, "Already paused");
isPaused = true;
}
function unpause() public {
require(isPaused, "Not paused");
isPaused = false;
}
function doSomething() public {
require(isInitialized, "Not initialized");
require(!isPaused, "Contract is paused");
require(!isFinalized, "Contract is finalized");
// 业务逻辑
}
}
pragma solidity ^0.8.0;
contract FeatureFlags {
bool public tradingEnabled;
bool public stakingEnabled;
bool public withdrawalEnabled;
address public owner;
constructor() {
owner = msg.sender;
tradingEnabled = true;
stakingEnabled = false;
withdrawalEnabled = true;
}
function toggleTrading() public {
require(msg.sender == owner, "Not owner");
tradingEnabled = !tradingEnabled;
}
function trade() public {
require(tradingEnabled, "Trading is disabled");
// 交易逻辑
}
function stake() public {
require(stakingEnabled, "Staking is disabled");
// 质押逻辑
}
}
pragma solidity ^0.8.0;
contract WhitelistBlacklist {
mapping(address => bool) public whitelist;
mapping(address => bool) public blacklist;
function addToWhitelist(address user) public {
whitelist[user] = true;
}
function addToBlacklist(address user) public {
blacklist[user] = true;
}
function canTransfer(address user) public view returns (bool) {
// 黑名单中的用户不能转账
if (blacklist[user]) {
return false;
}
// 如果有白名单机制,必须在白名单中
// return whitelist[user];
return true;
}
function transfer(address to) public {
require(canTransfer(msg.sender), "Transfer not allowed");
require(canTransfer(to), "Recipient cannot receive");
// 转账逻辑
}
}
布尔值在存储时占用一个完整的存储槽(32字节),即使它只需要1位来表示。
pragma solidity ^0.8.0;
contract BoolStorage {
// 每个 bool 单独占用一个存储槽
bool public flag1; // 槽 0
bool public flag2; // 槽 1
bool public flag3; // 槽 2
// 更好的方式:将多个 bool 与其他小类型变量一起声明
// 它们会被打包到同一个存储槽中,节省 Gas
bool public flag4; // 槽 3
uint8 public value1; // 槽 3(与 flag4 打包)
uint8 public value2; // 槽 3(与 flag4 打包)
address public addr; // 槽 3(与 flag4 打包,地址20字节)
}
提示: 目前只需要了解布尔变量可以和其他小变量打包存储即可。更深入的存储优化技术,可以在掌握基础知识后学习。
pragma solidity ^0.8.0;
contract AccessControlPractice {
address public owner;
mapping(address => bool) public admins;
constructor() {
owner = msg.sender;
}
// TODO: 实现检查是否为 owner 或 admin 的函数
function isAuthorized(address user) public view returns (bool) {
// 你的代码
}
// TODO: 实现只有授权用户才能调用的函数
function restrictedAction() public {
// 你的代码
}
}
pragma solidity ^0.8.0;
contract FeatureToggle {
bool public feature1Enabled;
bool public feature2Enabled;
// TODO: 实现切换功能开关
function toggleFeature1() public {
// 你的代码
}
// TODO: 实现检查所有功能是否都启用
function allFeaturesEnabled() public view returns (bool) {
// 你的代码
}
// TODO: 实现至少一个功能启用的检查
function anyFeatureEnabled() public view returns (bool) {
// 你的代码
}
}
true 和 false 两个值,默认值为 false&&(与)、||(或)、!(非)用于组合条件&& 和 || 支持短路求值,可以提高效率和避免错误==、!=、<、<=、>、>= 返回布尔值布尔类型虽然简单,但在智能合约中有着广泛而重要的应用。掌握布尔类型和逻辑运算符是编写智能合约的基础技能。
想了解更多关于布尔类型的高级应用,可以参考:
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!