function mint(address receiver, uint amount) public { require(msg.sender == minter); balances[receiver] += amount; }
// Errors allow you to provide information about // why an operation failed. They are returned // to the caller of the function. error InsufficientBalance(uint requested, uint available);
function send(address receiver, uint amount) public { if (amount > balances[msg.sender]) revert InsufficientBalance({ requested: amount, available: balances[msg.sender] });
event Sent(address from, address to, uint amount):
这行声明了一个所谓的“事件(event)”,它会在 send 函数的最后一行被发出。用户界面(当然也包括服务器应用程序)可以监听区块链上正在发送的事件,而不会花费太多成本。一旦它被发出,监听该事件的listener都将收到通知。而所有的事件都包含了 from , to 和 amount 三个参数,可方便追踪交易。
contract C { uint public data = 30; uint internal iData= 10;
function x() public returns (uint) { data = 3; // 内部访问 return data; } } contract Caller { C c = new C(); function f() public view returns (uint) { return c.data(); // 外部访问 } } contract D is C { uint storedData; // 状态变量
function y() public returns (uint) { iData = 3; // 派生合约内部访问 return iData; } function getResult() public view returns(uint){ uint a = 1; // 局部变量 uint b = 2; uint result = a + b; return storedData; // 访问状态变量 } }
contract test { enum FreshJuiceSize{ SMALL, MEDIUM, LARGE } FreshJuiceSize choice; FreshJuiceSize constant defaultChoice = FreshJuiceSize.MEDIUM;
function setLarge() public { choice = FreshJuiceSize.LARGE; } function getChoice() public view returns (FreshJuiceSize) { return choice; } function getDefaultChoice() public pure returns (uint) { return uint(defaultChoice); } }
contract test { struct Book { string title; string author; uint book_id; } Book book;
function setBook() public { book = Book('Learn Java', 'TP', 1); } function getBookId() public view returns (uint) { return book.book_id; } }
映射(mapping)
1
mapping(_KeyType => _ValueType)
_KeyType :可以是任何内置类型,或者bytes和字符串。不允许使用引用类型或复杂对象
_ValueType : 可以是任何类型
注意
映射的数据位置(data location)只能是storage,通常用于状态变量
映射可以标记为public,Solidity 自动为它创建getter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
pragma solidity ^0.5.0;
contract LedgerBalance { mapping(address => uint) public balances;
function updateBalance(uint newBalance) public { balances[msg.sender] = newBalance; } } contract Updater { function updateBalance() public returns (uint) { LedgerBalance ledgerBalance = new LedgerBalance(); ledgerBalance.updateBalance(10); return ledgerBalance.balances(address(this)); } }
对示例代码写一点自己的理解:
address是不可被运算的数据类型,因此需要map映射为uint,再参与运算
类型转换
可以使用构造函数语法,显式地将数据类型转换为另一种类型。
1 2 3
int8 y = -3; uint x = uint(y); //Now x = 0xfffff..fd == 在256bit长度的格式下,-3的补码表示
转换成更小的类型,会丢失高位。
1 2
uint32 a = 0x12345678; uint16 b = uint16(a); // b = 0x5678
转换成更大的类型,将向左侧添加填充位。
1 2
uint16 a = 0x1234; uint32 b = uint32(a); // b = 0x00001234
转换到更小的字节类型,会丢失后面数据。
1 2
bytes2 a = 0x1234; bytes1 b = bytes1(a); // b = 0x12
转换为更大的字节类型时,向右添加填充位。
1 2
bytes2 a = 0x1234; bytes4 b = bytes4(a); // b = 0x12340000
只有当字节类型和int类型大小相同时,才可以进行转换。
1 2 3 4 5
bytes2 a = 0x1234; uint32 b = uint16(a); // b = 0x00001234 uint32 c = uint32(bytes4(a)); // c = 0x12340000 uint8 d = uint8(uint16(a)); // d = 0x34 uint8 e = uint8(bytes1(a)); // e = 0x12
把整数赋值给整型时,不能超出范围,发生截断,否则会报错。
1 2 3
uint8 a = 12; // no error uint32 b = 1234; // no error uint16 c = 0x123456; // error, 有截断,变为 0x3456
function function-name(parameter-list) scope returns() { //语句 }
return语句可以返回多个值
1 2 3 4 5 6 7 8 9 10 11 12 13
pragma solidity ^0.5.0;
contract Test { function getResult() public view returns(uint product, uint sum){ uint a = 1; // 局部变量 uint b = 2; product = a * b; // 使用返回参数返回值 sum = a + b; // 使用返回参数返回值
contract Test { function getSum(uint a, uint b) public pure returns(uint){ return a + b; } function getSum(uint a, uint b, uint c) public pure returns(uint){ return a + b + c; } function callSumWithTwoArguments() public pure returns(uint){ return getSum(1,2); } function callSumWithThreeArguments() public pure returns(uint){ return getSum(1,2,3); } }
contract Base { uint data; constructor(uint _data) public { data = _data; } } contract Derived is Base (5) { constructor() public {} }
可以使用以下方法间接初始化基构造函数
1 2 3 4 5 6 7 8 9 10 11
pragma solidity ^0.5.0;
contract Base { uint data; constructor(uint _data) public { data = _data; } } contract Derived is Base { constructor(uint _info) Base(_info * _info) public {} }
不允许直接或间接地初始化基合约构造函数。
如果派生合约没有将参数传递给基合约构造函数,则派生合约将成为抽象合约。
抽象合约
1 2 3 4 5 6 7 8 9 10 11 12 13 14
pragma solidity ^0.5.0;
contract Calculator { function getResult() public view returns(uint); }
contract Test is Calculator { function getResult() public view returns(uint) { uint a = 1; uint b = 2; uint result = a + b; return result; } }
interface Calculator { function getResult() external view returns(uint); }
contract Test is Calculator { constructor() public {} function getResult() external view returns(uint){ uint a = 1; uint b = 2; uint result = a + b; return result; } }