1、Todolist(日程表)练习
包括增删改查和使用地址获取结构体
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract Todolist{
struct Todo{
string text;
bool complete;
}
Todo[] public todos;
//构建能够从地址映射构建内容的mapping
mapping(address=>Todo) public WhoOwnTodo;
function create(string calldata _text) external{
Todo memory todo;
todo.text = _text;
todo.complete = false;
todos.push(todo);
// todos.push(Todo({
// text:_text,
// complete:false
// }));
WhoOwnTodo[msg.sender] = todo;
}
function updateText(uint _index,string calldata _text) external{
//如果仅需要修改结构体中的一个内容:
todos[_index].text = _text;
//如果需要修改结构体中的多个内容:
// Todo storage todo = todos[_index];
// todo.text = _text;
// todo.complete = true;
}
//根据索引获取数组
function get(uint _index) external view returns(string memory,bool){
//将todo装在storage中比装在内存memory中的gas更少。
Todo storage todo = todos[_index];
return (todo.text,todo.complete);
}
function change_complete(uint _index) external{
todos[_index].complete = !todos[_index].complete;
}
function gettodo(address _addr) external view returns(Todo memory){
return WhoOwnTodo[_addr];
}
}
2、事件event
是用于记录当前智能合约运行状态的方法,体现在区块链浏览器上以及交易记录的log,通过事件可以查询改变过的状态。
包括构建事件和触发事件。
事件是写入方法,不能标记为view和pure。
Log:自定事件
IndexedLog:具有索引的事件,可以利用用户地址查询所有用户在区块链上发生过的事情。类似传统数据库的检索,有索引的变量最多只能有三个。
Message:有from和to地址,该事件具有两个区块链地址。
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract Event{
//log是可自定义的事件
event Log(string message,uint val);
//据有索引的事件,当索引不同时,值也不同
event IndexedLog(address indexed sender,uint val);
function example() external{
emit Log("foo",1234);
emit IndexedLog(msg.sender,789);
}
//包含从A地址到B地址以及相关信息的事件
event Message(address indexed _from,address indexed _to, string message);
function sendMessage(address _to, string calldata message) external{
emit Message(msg.sender, _to, message);
}
}
3、继承
合约继承:B is A
合约方法覆写:virtual、override
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
//能够被覆写的函数能需要使用virtual修饰词
contract A{
function foo() public virtual pure returns (string memory) {
return"A";
}
function bar() public virtual pure returns (string memory) {
return"A";
}
//more code
function baz() public pure returns (string memory){
return"A";
}
}
//在覆写函数的时候需要使用override修饰词
contract B is A{
function foo() public pure override returns (string memory){
return"B";
}
function bar() public override virtual pure returns (string memory){
return"B";
}
}
contract C is B{
function bar() public override pure returns (string memory){
return"C";
}
}
4、多线继承
多线继承是指:
X
/ |
Y |
\ |
Z
Y继承X,Z继承X和Y,这种多重继承关系。
在构建多线继承时,要先梳理继承关系,在新的函数继承时,将继承最少的函数放在最前面,继承最多的函数放在最后面。
并且要在override后添加继承的合约名称
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract X{
function foo() public pure virtual returns(string memory){
return "X";
}
function bar() public pure virtual returns(string memory){
return "X";
}
function x() public pure returns(string memory){
return "X";
}
}
contract Y is X{
function foo() public pure virtual override returns(string memory){
return "Y";
}
function bar() public pure virtual override returns(string memory){
return "Y";
}
function y() public pure returns(string memory){
return "Y";
}
}
contract Z is X,Y{
function foo() public pure virtual override(X,Y) returns(string memory){
return "Z";
}
function bar() public pure virtual override(X,Y) returns(string memory){
return "Z";
}
}
5、继承的构造函数
按照继承的顺序进行构造
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract A{
string public name;
constructor(string memory _name){
name = _name;
}
}
contract B{
string public text;
constructor(string memory _text){
text = _text;
}
}
//提前输入固定的内容进行子合约的构造函数设定
contract V is A("A"),B("B"){
}
//通过后续输入信息来传导构造函数
contract VV is A,B{
constructor(string memory _name,string memory _text) A(_name) B(_text) {
}
}
contract VVV is A("a"),B{
constructor(string memory _text) B(_text){
}
}
6、调用父合约已被重写的函数
可以使用子合约调用已经被重写了的函数。
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract E{
event Log(string message);
function foo() public virtual{
emit Log("E.foo");
}
function bar() public virtual{
emit Log("E.bar");
}
}
contract F is E{
function foo() public override{
emit Log("F.foo");
E.foo();
}
function bar() public override{
emit Log("F.bar");
super.bar();
}
}
7、可视范围
private 仅内部合约可使用,外部和继承合约不可使用
internal 内部合约和继承合约可使用,外部不可使用
public 内部、继承和外部均可使用
external 内部、外部可使用,继承合约不可使用
8、不可变量
immutable:用于函数修饰词,该函数在构建合约时作为变量,以后变为不可修改的常量,用于减少gas。
9、支付ETH
payable:可向合约发布主币
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract Payable{
address payable public owner;
constructor(){
owner = payable(msg.sender);
}
function deposit() external payable{}
function getBalance() external view returns (uint) {
return address(this).balance;
}
}