1. 单位
1.1. 常用单位
wei是以太币(ETH)的最小单位(1wei== 1)gwei是描述汽油价格时常用的单位(1gwei== 1e9)以太单位 (1以太== 1e18)
注:
在 Solidity 中,我们将使用整数进行计算,且该语言不支持浮点数类型。浮点数表示法的问题会导致舍入误差(四舍五入) 从而为攻击者制造了逻辑漏洞。
1.2. 时间单位
- 1 == 1
秒 - 1
会议纪要== 60秒 - 1
小时== 60会议纪要 - 1
天== 24小时 - 1
周== 7天
示例
function f(uint start, uint daysAfter) public {
if (block.timestamp >= start + daysAfter * 1 days) {
// ...
}
}2. 全局变量
2.1. 区块和交易属性
blockhash(uint blockNumber) 返回 (bytes32):给定区块的哈希值,当区块号是最近的 256 个区块之一;否则返回零block.basefee (uint): 当前区块的基础手续费block.chainid (uint): 当前链 IDblock.coinbase(收款地址): 当前区块矿工的地址block.gaslimit (uint): 当前区块的 gas 限制区块号 (uint): 当前区块号block.timestamp (uint): 当前区块时间戳(以自Unix纪元以来的秒数表示)gasleft() 返回 (uint256): 剩余燃气msg.data(字节 calldata): 完整的调用数据msg.sender (地址): 消息发送者(当前通话)msg.sig (4字节):调用数据的头四个字节(即函数标识符)msg.value (uint): 随消息发送的wei数量tx.gasprice (uint): 交易的手续费tx.origin(地址): 交易发起者(完整调用链)
2.2. 错误处理
assert(bool condition): 如果条件未满足,将引发 Panic 错误并导致状态回滚——用于内部错误。require(bool condition): 如果条件未满足则回退——用于处理输入或外部组件中的错误。require(bool 条件, string 内存提示): 如果条件未满足则回退——用于处理输入或外部组件中的错误。同时会显示一条错误信息。revert():中止执行并回滚状态变更revert(字符串 内存 原因):中止执行并回滚状态变更,同时提供一条说明性字符串
2.3. 地址类型的成员
<address>.balance (uint256):魏国诏书的其余部分<address>.code (bytes memory): 地址处的代码(可以为空)<address>.codehash (bytes32):该地址的代码哈希值<address payable>.transfer(uint256 amount): 将指定数量的 Wei 发送至指定地址,若操作失败则回滚,并支付 2300 gas 费用,该数值不可调整<address payable>.send(uint256 amount) returns (bool): 将指定数量的 Wei 发送至指定地址,失败时返回 false,预付 2300 gas,不可调整<address>.call(bytes memory) returns (bool, bytes memory): 使用给定的有效载荷调用低级 CALL 函数,返回成功状态和返回数据,转发所有可用 gas,可调整<address>.delegatecall(bytes memory) returns (bool, bytes memory): 使用给定的有效载荷调用低级 DELEGATECALL,返回成功状态和返回数据,转发所有可用 gas,可调整<address>.staticcall(bytes memory) returns (bool, bytes memory): 使用给定的有效载荷发出低级 STATICCALL 调用,返回成功状态和返回数据,转发所有可用 gas,可调整
2.4. 与合同相关的关键词
这个: 当前合约,可明确转换为 Address超级: 在继承层次结构中比当前级别高一级别的契约selfdestruct(收款人地址): 销毁当前合约,将资金转至指定的地址,并终止执行。请注意,selfdestruct 继承了 EVM 的一些特殊性:- 接收合同的接收函数未被执行。
- 合约实际上只有在交易结束时才会被销毁,而回滚操作可能会“撤销”这一销毁。
3. 表达式与控制结构
3.1. 支持的关键词
有: 如果, 否则, 虽然, 做, 为, 换行, 继续, 返回, 试一试/捕获 采用与 C 或 JavaScript 中相同的语义。
3.2. 函数调用
我们可以称 函数 第 1 页 合同 来自另一个 合同. 下面是一个包含 2 份合同的示例 来电者 以及 卡莉.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Callee {
uint public x;
uint public value;
function setX(uint _x) public returns (uint) {
x = _x;
return x;
}
function setXandSendEther(uint _x) public payable returns (uint, uint) {
x = _x;
value = msg.value;
return (x, value);
}
}
contract Caller {
function setX(Callee _callee, uint _x) public {
uint x = _callee.setX(_x);
}
function setXFromAddress(address _addr, uint _x) public {
Callee callee = Callee(_addr);
callee.setX(_x);
}
function setXandSendEther(Callee _callee, uint _x) public payable {
(uint x, uint value) = _callee.setXandSendEther{value: msg.value}(_x);
}
}3.3. 使用关键字创建新合约 新
我们可以使用关键词 新 创建一份新合同。 AdvancedStorage.sol 下面这个例子将对此进行更详细的说明。
4. 高级存储
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract AdvancedStorage {
// Declare the address of a vault manager
address public vaultManager;
// Declare an error type for unauthorized access
error OwnableUnauthorizedAccount(address account);
// Constructor is a function that runs when the contract is initialized
constructor() {
// Assign the address of the deployer to the vault manager variable
vaultManager = msg.sender;
}
// Declare the InvestmentVault Struct data type
struct InvestmentVault {
uint256 investmentDuration; // Thời gian đầu tư
int256 returnOnInvestment; // % lãi suất trả về
bool initialized; // Đã khởi tạo
address identityCard; // Địa chỉ thẻ thông tin
}
// Declare a variable with the InvestmentVault type
InvestmentVault private investmentVault;
// This function initializes the investment vault
function setInitialInvestmentVault(uint256 daysAfter, int256 _returnOnInvestment, address _vaultOwner) public {
// We check if the initiator is the vaultManager
if (msg.sender != vaultManager) {
// This reverts all actions and reverts the transaction
revert OwnableUnauthorizedAccount(msg.sender);
}
// Declare the investment duration
uint256 _investmentDuration = block.timestamp + daysAfter * 1 days;
// Create a new identity card for the customer
CustomerIdentityCard customerIdentityCard = new CustomerIdentityCard(_vaultOwner);
// Assign the address of the vault owner/customer to the mapping with the vault information
investmentVault = InvestmentVault({investmentDuration: _investmentDuration, returnOnInvestment: _returnOnInvestment, initialized: true, identityCard: address(customerIdentityCard)});
}
// Function to change the return on investment
function editReturnOnInvestment(int256 _newReturnOnInvestment) public {
// require keyword works similarly to if and revert above
require (msg.sender == vaultManager, "Unauthorized Manager");
// Change the value of the interest rate
investmentVault.returnOnInvestment = _newReturnOnInvestment;
}
// Function to return investmentVault information
function retrieveInvestmentVault() public view returns (InvestmentVault memory _investmentVault) {
return investmentVault;
}
// Function to return the address of the IdentityCard
function retrieveCustomerInformation() public view returns (address) {
return CustomerIdentityCard(investmentVault.identityCard).customer();
}
}
// Contract that stores the address of the vault owner
contract CustomerIdentityCard {
// declares a variable to store the address of the customer
address public customer;
// initialize the contract and assign the address of the customer
constructor(address _customer) {
customer = _customer;
}
}