uint256
。 示例:uint256 myNumber = 10;
bool isTrue = true;
address myAddress = 0xAbcdef1234567890;
string myString = "Hello, World!";
uint256[] myArray = [1, 2, 3];
用于自定义复合类型,可以包含多个字段。 示例:
Copy Code
struct Person {
string name;
uint age;
}
Person myPerson;
myPerson.name = "Alice";
myPerson.age = 25;
Enum
是枚举类型,可以通过以下语法来定义
enum Status {
Unknown,
Start,
End,
Pause
}
并通过以下语法来进行更新与初始化
// 实例化枚举类型
Status public status;
// 更新枚举值
function pause() public {
status = Status.Pause;
}
// 初始化枚举值
function reset() public {
delete status;
}
Copy Code
mapping(address => uint256) balances;
balances[msg.sender] = 100;
用于标识一个函数不会修改合约的状态,即它只能读取数据而不能修改数据。这意味着在调用视图函数时,不会产生任何交易费用,并且不会改变合约的状态。例如:
function getName() public view returns (string memory) {return name; }
用于标识一个函数既不会修改合约的状态,也不会读取或访问合约的存储数据。这种函数通常用于执行纯粹的计算操作,不涉及存储或外部调用。例如:
function add(uint256 a, uint256 b) public pure returns (uint256) {return ab; }
string public name = "Alice";
uint256 private balance = 100;
将函数声明为外部函数,只能从合约外部调用。与 "public" 关键字不同的是,外部函数不能在合约内部直接调用,也不能被合约继承。例如:
Copy Code function transfer(address recipient, uint256 amount) external { // transfer logic here }
将函数声明为内部函数,只能在合约内部或合约继承链上的合约中访问。例如:
function withdraw(uint256 amount) internal { // withdraw logic here }
将函数声明为可以接收以太、币的函数,在函数中可以接收以太币并进行转账操作。例如:
function purchase() public payable {// purchase logic here }
Copy Code
function sayHello(string memory name) public {// 函数逻辑// ...
}
sayHello("Alice");
Copy Code
function myFunction() public {// 可公开访问的函数
}
function privateFunction() private {// 私有函数,只能在合约内部调用
}
用于修改函数的行为。 示例:
Copy Code
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can call this function.");_;
}
function changeName(string memory newName) public onlyOwner {// 只有合约所有者可以调用该函数
name = newName;
}
Copy Code
function add(uint256 a, uint256 b) public pure returns (uint256) {return a + b;
}
uint256 result = add(2, 3); // result = 5
uint256[] myArray; // 空数组uint256[] myArray2 = new uint256[](3); // 长度为3的动态数组uint256[] myArray3 = [1, 2, 3]; // 直接初始化数组
length
属性获取数组长度,并通过索引访问数组元素。 示例:
uint256[] myArray = [1, 2, 3]; uint256 length = myArray.length; // length = 3uint256 secondElement = myArray[1]; // secondElement = 2
uint256[] dynamicArray;
uint256[3] staticArray;
uint256[][] twoDimensionalArray;
uint256[2][3] twoByThreeArray;
struct Person {
string name;
uint age;
}
Person myPerson;
myPerson.name = "Alice";
myPerson.age = 25;
Person myPerson;
myPerson.name = "Alice";
string memory personName = myPerson.name; // personName = "Alice"
struct Person {
string name;
uint age;
}
function getPerson() public view returns (Person memory) {
Person memory person;
person.name = "Alice";
person.age = 25;
return person;
}
Person memory myPerson = getPerson();
结构体可以组成数组,并通过索引访问数组元素。 示例:
struct Person {
string name;
uint age;
}
Person[] people;
Person memory person1;
person1.name = "Alice";
person1.age = 25;
people.push(person1);
Person memory person2;
person2.name = "Bob";
person2.age = 30;
people.push(person2);
当在Solidity中声明变量时,可以使用不同的存储位置修饰符来指定变量应该存储在何处。共有三种存储位置:memory
、storage
和calldata
。其中,memory
和storage
是最常用的两种。
memory
:
memory
是一种临时存储位置,用于存储函数执行期间的临时数据。它适用于需要在函数内部进行临时计算或处理大量数据的情况。在函数执行完毕后,memory
中的数据会被清空。
memory
关键字将变量声明为 memory
类型,也可以在函数参数中使用 memory
。 示例:
function processArray(uint256 memory myArray) public {// 在 memory 中处理数组// ... }
storage
:
storage
是一种永久性存储位置,用于在合约的存储空间中存储和访问数据。它适用于需要在不同函数之间共享和保留数据的情况。在合约中声明的 state variables
默认是 storage
类型。
storage
类型的变量,无需显式声明。 示例:
calldata
:
calldata
是一种特殊的存储位置,用于存储函数参数和外部函数调用的输入数据。calldata
中的数据是只读的,不能被修改。此存储位置适用于函数参数传递和与外部合约交互。
mapping
类型参数都被视为 calldata
类型。 示例:
function processInputData(uint256 calldata inputData) external {// 处理输入数据
}
function callExternalContract(address externalContract, bytes calldata data) external {
(bool success, ) = externalContract.call(data);
require(success, "External contract call failed.");
}
总结一下:
memory
用于临时存储函数执行期间的数据,适用于临时计算或处理大量数据的情况;
storage
用于永久性存储变量,适用于在不同函数之间共享和保留数据的情况;
calldata
用于存储函数参数和外部函数调用的输入数据,是只读的。
Solidity 中的堆栈主要用于函数调用的内部状态维护。每当一个函数被调用时,它会在堆栈上创建一个新的帧,该帧包含了这个函数的参数、局部变量、返回地址等信息。当函数执行完毕后,该帧将从堆栈中弹出。
通常情况下,开发者不需要手动操作堆栈,Solidity 编译器会自动进行堆栈管理。但在一些需要优化调用栈空间的场景下,可能需要手动控制函数调用堆栈的大小和顺序。 示例:
function foo(uint256 x, uint256 y) public pure returns (uint256) {
uint256 result = bar(x) + y;return result;
}
function bar(uint256 x) public pure returns (uint256) {
uint256 result = x * 2;return result;
}
emit
关键字触发。日志数据会被写入到交易的日志中,不会影响合约状态,但会占用一定的 Gas。 示例:
event Transfer(address indexed from, address indexed to, uint256 value);
function transfer(address _to, uint256 _value) public {
require(balances[msg.sender] >= _value, "Insufficient balance.");
balances[msg.sender] -= _value;
balances[_to] += _value;
emit Transfer(msg.sender, _to, _value);
}
Solidity 中的一种特殊的数据类型,用于存储合约的字节码。
在 Solidity 中,合约代码(也称为字节码)可以通过 type
关键字将其存储在 bytes
或 bytescode
类型的变量中。这样可以在合约内部或外部对代码进行处理和分析。
以下是一个简单的示例,展示了如何将合约代码存储在 bytes
类型的变量中:
pragma solidity ^0.8.0;
contract CodeExample {
bytes public contractCode;
constructor() {
// 将合约代码存储在 contractCode 变量中
contractCode = type(CodeExample).creationCode;
}
}
mapping(address => uint256) balances;
mapping(address => uint256) balances;
address account = 0xAbcdef1234567890; balances[account] = 100;
mapping(address => uint256) balances;
address account = 0xAbcdef1234567890; uint256 balance = balances[account]; // 获取映射值 balances[account] = 200; // 修改映射值
在 Solidity 中,映射(Mapping)是一种键值对的数据结构,类似于字典或哈希表。每个键对应一个唯一的值。但是,Solidity 中的映射并不支持直接迭代,这意味着你无法像遍历数组或列表那样直接对映射进行循环迭代。