Solidity语言详解
1.文件结构
2.数据结构
3.错误处理
11.参数
12.控制结构
13.可见性
14.函数
1.1合约文件结构
1.1.1版权申明
1.1.2import
1.1.3合约
1.1.3.1状态变量
1.1.3.2函数
1.1.3.3结构类型
1.1.3.4事件
1.1.3.5函数修改器
1.1.4代码注释
语言类型
动态:运行时确定某个变量类型 egg:javascript
静态:声明的时候,编译的时候,指定变量类型或者至少编译时推导出类型,常见的有c,c++,java
solidity静态
值类型 重点booleans integers string address
引用类型
布尔类型
取值 true/false
运算符! && || == !=
整型
int/unit
关键字unit8到unit256(以8步进)
运算符
-比较运算符
-位运算符&,|,^,~
算术运算
常量(字面量)
有理数和整型常量
字符串常量
十六进制常量
地址常量
地址类型
address:表示一个账户地址(20字节)
成员 属性:balance余额 函数:transfer()用于转移以太币
地址常量
地址合法性检查
引用类型
数据位置 memory内存,storage永久
数组
-T[k]:元素类型为T,固定长度为k的数组
-T[]:数组类型为T,长度动态调整
-bytes string:是一种特殊的数组
-string 可转为bytes,bytes类似byte[]
数组成员:属性:length 函数:push()
结构体
struct
映射(Mappings)
mapping(address=>uint) public balances;
全局变量和函数
-有关区块和交易!
msg.sender(address)获取交易发送者地址
msg.value(uint)当前交易所附带的以太币,单位是位
block.coinbase(address)当前块的地址
block.difficulty(uint)当前块的难度
block.number(uint)当前区块的块号
block.timestamp(uint)当前块时间戳
now(uint)当前区块的时间戳,实际上是timestamp的别名
tx.gasprice(uint)当前交易的价格
-有关错误处理!
什么是错误处理 指在程序发生错误时的处理方式
处理方式 回退状态 assert (通常检查函数内部的错误,消耗所有提供的gas,egg:下标越界,整数/0,assert方法调用参数时false,是assert类型异常)。require(检查输入的变量或者合约的状态变量是否满足条件,通常时外部 合约的条件,不会消耗提供的gas,egg:gas不足,没有匹配到正常的函数等等)
把区块链当作分布式事务性数据库:数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的 全部数据库操作组成。[1]
-有关数字及加密功能
-有关地址和合约
函数参数
-输入参数
-输出参数 函数的返回值
-命名参数 {a: 1, b: 3}
-参数解构 用在函数式编程比较多
控制结构
if,else,while,do,for,break结束本次循环,continue下一步,return,?:
没有switch goto
可见性
-public 函数默认可见性,公开函数是合约接口的一部分,可以通过内部,或者消息调用。对于public类型的状态变量,会自动创建一个访问器(可以理解为get函数)
-private 私有的函数和状态变量仅在 当前合约 中可以访问,在继承的合约内不可访问(不能修改,可以看到)
-external 外部函数是合同接口的一部分,只能使用 消息调用
-internal 状态变量默认的可见性,函数和状态只能通过内部访问。如在 当前合约 或 继承合约 里调用
表达式 this.g(8);和 c.g(2)(这里的 c 是一个合约实例)是外部调用函数的方式,它会发起一个消息调用
public和external区别 public多了一个调用方式,如果我们有一个函数,它只接收外部调用的话,使用external而不是public,因为external消耗gas更少
方式=内部+消息调用
内部=当前合约+继承合约
消息调用=this+c.g()
public为方式
private为方式->内部->当前合约
external为方式->消息调用
internal为方式->内部
函数
-构造函数
-视图函数(constant/view)(不会修改 状态变量)(不能触发事件-认为是修改状态变量)(不能创建合约)
-纯函数(pure)(既不会读也不会修改 状态变量)
-回退函数(无名函数,一个智能合约需要接受以太币的时候,我们就需要实现这样的回退函数,它是一个被动调用的函数)
pragma solidity ^0.4.0;
import "solidity_for_import.sol";
// This is a test Contract
contract Test {
uint a;
bool boola = true;
bool boolb = false;
int256 c = 20; // int256==int
int256 d = 30;
function testadd() public constant returns (int) {
if (b > c){
return b + c
} else if (b == c){
return b * c
} else {
return b >> 2
}
}
function testLiterals() public constant returns (int) {
return 1231321321.0 * 1.5e10;
}
function testStringLiterals() public constant returns (string) {
return "abc";
}
function testHexLiterals() public constant returns (bytes2, bytes1, bytes1) {
bytes2 a = hex"abcd"
return (a, a[0], a[1];)
}
function testbool1() returns (bool) {
return boola && boolb;
}
function testbool2() returns (bool) {
return boola || boolb;
}
function testbool3() returns (bool) {
return !boola
}
function setA(unit x) public {
a = x
emit Set_A(X);
}
event Set_A(uint a);
struct Position {
int lat:
int lng
}
address public owerAddr;
// 修改函数的行为 函数修改器
modifier owner () {
require(msg.sender == owerAddr);
_;
}
function mine() public owner {
a += 1;
}
}
solidity_for_import.sol
pragma solidity ^0.4.0;
contract ForImport {
}
pragma solidity ^0.4.0;
contract ArrayTest{
uint[] public u = [1, 2, 3];
string s = "abcdefg;
function h() public returns (uint) {
u.push(4);
return u.length;
}
function f() public view returns (byte) {
return bytes(s)[1];
}
function new(uint len) constant public returns (uint) {
uint[] memory a = new uint[] (len);
bytes memory b = new bytes(len);
a[6] = 8;
// 错a.length = 100;
// 对u.length = 100;
g([unit(1), 2, 3]);
return a.length;
}
function g(uint[3] _data) public constant {
}
struct Funder {
address addr;
uint amount;
}
Funder funder;
function newFunder() public {
funder = Funder({addr: msg.sender, amount: 10});
}
mapping(address=>uint) public balances;
function updateBalance(uiny newBalance) public {
balances[msg.sender] = newBalance
}
function testApi1() public constant returns (address) {
return msg.sender;
}
constructor() payable {
}
function testApi2() public payable returns (uint) {
return msg.value;
}
function testApi3() public constant returns (address) {
return block.coinbase;
}
function testApi4() public constant returns (uint) {
return block.difficulty;
}
function testApi5() public constant returns (uint) {
return block.number;
}
}
pragma solidity ^0.4.0;
contract Test{
function simpleIntput(uint a, uint b) public constant returns (uint sum, uint mul) {
sum = a + b
mul = a * b
}
function testSimpleInput() public constant returns (uint sum, uint mul) {
//sum = simpleIntput({a: 1, b: 3}); // 等于sum = simpleIntput({b: 1, a: 3});
(sum, mul) = simpleIntput({ b : 3, a : 1});
}
function f() public constant returns (uint, bool, uint) {
return (7, true, 2)
}
function g() public {
var (x, y, z) = f()
(, y, z) = f()
(x, ) = (1, 2);
// 交换x和z的值
(x, z) = (z, x)
}
}
pragma solidity ^0.4.0;
contract Test{
uint public data; // 生成访问器,可以理解为get函数
function f(uint a) privare returns (uint b) {
return a + 1;
}
function setData(uint a) internal {
data = a;
}
function exSetData(uint a) external {
data = a;
}
function testsetData() public {
setData(1);
this.exSetData(1); // 转化为消息的调用
}
function abc() public(){
testsetData();
this.testsetData();
}
}
contract Test2 is Test {
function setData(uint a) internal {
data = a
}
}
contract D {
function readData() public {
Test test = new Test();
test.setData(1);//x
test.exSetData(1);//y
tet.testsetData();//y
}
}
pragma solidity ^0.4.0;
contract Test{
uint internal data;
// 构造函数
constructor () public {
data = a;
}
event EVENTA(uint a);
// 视图函数
function testView() public constant returns (uint) { // constant是view别名
// data = 1 x 不能修改状态变量
// emit EVENTA(1); x 不能出发事件
return data;
}
// 纯函数
function f() public pure returns (uint) {
// return 1 * 2 + data; x 不能读取
// this.balance; x
// msg.value; x
return 1 * 2 + 3;
}
// 回退函数,一个函数只有一个回退函数,多个的话会出错
// 调用函数,
// 1.给这个合约发送以太币
// 2.我们在给我们调用的这样合约的函数,但是这个合约函数实际上并不存在,这个时候也会被动的调用这个回退函数
// 就是我们在调用一个合约,没有匹配到对应的函数的时候,它就会调用回退函数
// 需要注意的是,这样一个回退函数,我们可以在里面加一些实现,比如触发了一个事件等等,需要注意的是,里面的实现应该尽量简单
// 否则,在给这个合约转账的时候,发送者容易因为gas不足而交易失败
function () public payable {
emit EVENTA(1);
}
}
contract Caller {
// 合约想接受以太币,必须有回退函数 并且 必须带有payable
function callTest(Test test) public {
test.send(1 ether);
}
}
pragma solidity ^0.4.0;
contract AddrTest {
// 余额
function deposit() public payable {
}
// 地址
function getBalance() public constant returns (uint) {
return this.balance;
}
// 转账
function transferEther(address towho) public {
towho.transfer(10);
}
}
pragma solidity ^0.4.0
contract Sharer {
function sendHalf(address addr) public payable returns (uint balance) {
require(msg.value % 2 == 0);
uint balanceBeforeTranfer = this.balance
addr.transfer(msg.value / 2 + 1)
assert(this.balance == balanceBeforeTranfer - msg.value / 2)
return this.balance;
}
}