以太坊系列 - Solidity智能合约学习笔记

(1)账户地址

创建账号,无需上链,其实地址在链上非真实存在的,转账的接收方地址可以是任一符合规则的地址码,也能转账成功,只是没有人有与之匹配的私钥来操作此账户

geth节点重启,上链的数据还是保存着的

(2)合约内常用变量

  • msg.sender 就是当前调用方法的用户地址
  • this 指的是当前合约的地址
  • address 支持各种算数运算符
  • tx.origin 交易的发送者

(3)函数的可见性 public external internal private

  • public :函数默认声明为public 是合约对外接口的一部分

  • external :声明为external的可以从其它合约或通过Transaction进行调用, 是合约对外接口的一部分

    • 合约内变量没标名public或external,外部dapp无法获取
  • internal:在当前的合约或继承的合约中,只允许以internal的方式调用

  • private:只能在当前合约中被访问(不可在被继承的合约中访问)

    • 即使声明为private,仍能被所有人查看到里面的数据。访问权限只是阻止了其它合约访问函数或修改数据。

(4)合约的继承

存在继承关系的合约,只需要布置子合约(它的abi和bin信息中已经包含父合约的信息)

dapp中通过子合约的地址可以直接调父合约的函数

(5)合约A调用合约B

  • 合约A内定义一个合约B类型的变量,需要先部署合约B,再将B的address赋值给A内的合约B变量
  • 合约B变量未赋值时,无法使用
  • 合约B变量赋值后,dapp中通过A合约的地址可以间接调B合约的函数(封装成接口函数)
  • 合约A内调用带payable标识的合约B变量的函数,调用方法如下 :
    • 合约B变量.函数.value(给多少钱 将做为msg.value的值)(函数形参);
      例如: siringAuction.bid.value(msg.value - autoBirthFee)(_sireId);

(6)函数标识 payable 的作用

函数上有一个payable关键字,如果一个函数需要进行货币操作,必须要带上payable关键字,这样才能正常接收msg.value

(7)字符串比较

Solidity 并不支持原生的字符串比较, 只能通过比较两字符串的 keccak256 哈希值来进行判断

require(keccak256(_name) == keccak256("Vitalik"));

(8)多个合约文件

在 Solidity 中,当你有多个文件并且想把一个文件导入另一个文件时,可以使用 import 语句: 相同目录也必须用"./"开头

import "./someothercontract.sol";

(9)存储

Storage 变量是指永久存储在区块链中的变量。 Memory 变量则是临时的,当外部函数对某合约调用完成时,内存型变量即被移除

  • 当函数内使用Storage时,相当于指针 Sandwich storage mySandwich = sandwiches[_index];
  • 当函数内使用Memory时,相当于拷贝 Sandwich memory anotherSandwich = sandwiches[_index + 1];

(10)字节对齐

当 uint 定义在一个 struct 中的时候,尽量使用最小的整数子类型以节约空间。

并且把同样类型的变量放一起(即在 struct 中将把变量按照类型依次放置),这样 Solidity 可以将存储空间最小化

(11)如果合约想返回一个struct,得改用多个参数

如果合约返回多个参数,代码中定义一个结构体来接收,
且在定义的结构前使用[FunctionOutput],且使用CallDeserializingToObjectAsync来获取

(12)数组下标从0开始

(13)函数修饰符

  • view的作用和constant一模一样,可以读取状态变量但是不能改;
  • pure则更为严格,pure修饰的函数不能改也不能读状态变量,否则编译通不过。

(14)require(), assert(), revert()

在 0.4.10 版的 solidity,新增了 require(), assert(), revert() 。

  • require() 用來檢查較不嚴重的錯誤,可以退回未使用到的 gas。
  • assert() 用來檢查較嚴重的錯誤,會像以前一樣拿走所有 gasLimit 的手續費。寫法基本上都相同,只是處理方式不一樣。
  • revert 跟 require 基本上相同,但是 revert 沒有包括狀態檢查。

(15)tx.origin 和 msg.sender 有什么区别?

  • tx.origin 交易的发送者。
  • msg.sender 消息的发送者。

交易 transaction 可以包含1个或多个合约 contract。

  1. 一个合约时,对于合约本身来说,tx.origin 和 msg.sender 是同一个地址。
  2. 多个合约时,场景如: 用户,合约A ,合约B . 用户 通过合约A ,调合约B. 此时
    • 对于合约A: tx.originmsg.sender 都是用户。
    • 对于合约B: tx.origin 是用户 msg.sender 是合约A.

往期精彩回顾:
区块链知识系列
密码学系列
共识系列
公链调研系列
以太坊系列
EOS系列
智能合约系列
Token系列

版权声明:本文为wcc19840827原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。