1Ether = 10^3 Finney = 10^6 Szabo = 10^18 Wei
fallback 没有定义fallback function,在收到ether时,会触发exception并且退回ether。 contract想收ether必须定义fallback function,且要加上payable modifier来宣告function可以收取。 代码举例
1 2 3 4 5 6 7 8 9 10 11 pragma solidity ^0.4.25; contract FallbackExample{ event LogFallback(string message); event LogBalance(uint alance); function() public payable{ emit LogFallback("Fallback"); emit LogBalance(address(this).balance); } }
address type 格式 1 <address>.send(uint256 amount)
对address送出amount Wei 本function会forward 2300 gas 作为呼叫的 gas因为 send 将会出发address中的fallback function 当send失败,将回传 false 。否则回传 true 。 格式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <address>.transfer(uint256 amount) * 对address送出 amount Wei * 本 function 会 forward 2300 gas 作为呼叫的 gas * 因为 transfer 将会出发 address 中的 fallback function * 当执行失败,将 throw exception 。 ### Transfer V.S. Send * Transfer 保证了转移 Ether 的正确性,因为失败的实侯会让整个transaction 收到 throw 而终止 * Send 在执行失败只会回传 false, 因此在使用 Send 时,应该每次都检查他的回传值。比如搭配 require() 代码举例 ```sol pragma solidity ^0.4.25; contract Address{ function() public payable {} function Balance() public view returns (uint256){ return address(this).balance; } function Transfer(uint256 amount) public returns (bool){ msg.sender.transfer(amount * 1 ether); return true; } function SendWithoutCheck(uint256 amount) public returns (bool){ msg.sender.send(amount * 1 ether); return true; } function SendWithCheck(uint256 amount) public returns (bool){ require(msg.sender.send(amount * 1 ether),"Send failed"); return true; } }
Mapping 格式 mapping (T1 => T2) var;
提供 Key -> Value 的资料结构 T1 可以是除了 mapping 以外的所有 type,因为实际存储的时候,T1 原本的数据并不会被存储下来,只会留下 keccake256(T1) 作为 index。 T2 可以是任何 type 代码实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 pragma solidity ^0.4.25; contract Donation { mapping(address => uint) public ledger; mapping(address => bool) public donors; address[] public donorList; function isDonor(address pAddr) internal view returns(bool){ return donors[pAddr]; } function donate() public payable{ if(msg.value >= 1 ether){ if(!isDonor(msg.sender)){ donors[msg.sender] = true; donorList.push(msg.sender); } ledger[msg.sender] += msg.value; } else { revert("< 1 ether"); } } }
struct 格式
1 2 3 4 struct Name{ T var; ... }
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 pragma solidity ^0.4.25; contract Class{ struct Student{ string name; uint score; bool active; } mapping(uint => Student) students; modifier ActiveStudent(uint id){ require(students[id].active,"Student is inactive"); _; } function register(uint id,string name) public{ students[id] = Student({name:name,score:0,active:true}); } function modifyScore(uint id,uint score) public ActiveStudent(id){ students[id].score = score; } function getStudent(uint id) public ActiveStudent(id) view returns (string,uint){ return (students[id].name,students[id].score); } }
实况捐赠合约实例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 pragma solidity ^0.4.25; contract Donation{ struct DonorInfo{ address[] donors; mapping (address => uint) ledger; } mapping (address => DonorInfo) DonationHistory; event LogDonate(address streamer,address donor, string nickname,uint value,string message); function donate(address _streamer,string _nickname,string _message) public payable{ require(msg.value > 0); _streamer.transfer(msg.value); if(DonationHistory[_streamer].ledger[msg.sender] == 0) { DonationHistory[_streamer].donors.push(msg.sender); } DonationHistory[_streamer].ledger[msg.sender] += msg.value; emit LogDonate(_streamer,msg.sender,_nickname,msg.value,_message); } function getDonorList() public view returns(address[]){ return DonationHistory[msg.sender].donors; } event LogListDonorInfo(address streamer,address user,uint value); function listDonorInfo() public{ for(uint i = 0;i < DonationHistory[msg.sender].donors.length;i++){ address user = DonationHistory[msg.sender].donors[i]; emit LogListDonorInfo(msg.sender,user,DonationHistory[msg.sender].ledger[user]); } } }
Abstract 代码实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 pragma solidity ^0.4.25; contract Ownable{ address private owner; construcotr() internal { owner = msg.sender; } modifier onlyOwner(){ require(isOwner()); _; } function isOwner() public view returns (bool){ return owner == msg.sender; } } contract Main is Ownable{ string public name = ""; function modifyName(string _name) public onlyOwner{ name = _name; } }
Interface 只能定义function 不能继承其他contracts & interfaces 不能定义 constructor、变数、struct、enum 代码实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 pragma solidity ^0.4.25; interface Animal { function run(uint speed) external returns (uint); } contract Cat is Animal{ function run(uint speed) public returns (uint distance){ return speed * speed; } } contract Dog is Animal{ function run(uint speed) public returns(uint distance){ return speed * 10; } }
library 格式:library lib{}
希望能只被部署一次且在一个指定的位置,但能被多个地方所使用 没有state variables 不能继承他人,也不能被继承 无法接受Ether 代码实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 pragma solidity ^0.4.25; library Set{ struct Data{ mapping(int => bool) data; } function Insert(Data storage d,int key) public returns (bool){ if(d.data[key]) return false;//Key exists d.data[key] = true; return true; } function Remove(Data storage d,int key) public returns (bool){ if(!d.data[key]) return false;//Key does not exists d.data[key] = false; return true; } function Contain(Data storage d,int key) public view returns (bool) { return d.data[key]; } } contract Main{ Set.Data set; function insert(int key) public returns (bool) { return Set.Insert(set,key); } function remove(int key) public returns (bool) { return Set.Remove(set,key); } function contain(int key) public view returns (bool) { return Set.Contain(set,key); } }
SafeMath 代码实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 pragma solidity ^0.4.25; library SafeMath{ function mul(uint256 a,uint256 b) internal pure returns (uint256) { uint256 c = a * b; require( c / a == b); return c; } function div(uint256 a,uint256 b) internal pure returns (uint256) { require(b > 0); // solidity only automatically asserts when dividing by 0 uint256 c = a / b; return c; } function sub(uint256 a,uint256 b) internal pure returns (uint256) { require(b <= a); // underflow uint256 c = a - b; return c; } function add(uint256 a,uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a); // overflow return c; } function mod(uint256 a,uint256 b) internal pure returns (uint256) { require(b != 0); return a % b; } } contract Main{ function test() public pure returns (uint256){ uint256 a = 300; uint256 b = 10; return SafeMath.add(a,b); } }
Import & using 格式:import “a.sol”; 格式:using lib for type;
代码实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 pragma solidity ^0.4.25; import "browser/library & set.sol"; contract Main{ using Set for Set.Data; Set.Data myset; function insert(int key) public returns (bool) { return mySet.Insert(key); } function remove(int key) public returns (bool) { return mySet.Remove(key); } function contain(int key) public view returns (bool) { return mySet.Contain(key); } }
IERC20 interface 代码实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 pragma solidity ^0.4.25; interface IERC20 { // suo'you所有cun'zai所有存在的 Token 数量 function totalSupply() external view returns (uint256); // 读取 tokenOwner 这个 address 所持有的 Token 数量 function balanceOf(address tokenOwner) external view returns (uint256 balance); // 从 msg.sender 传 tokens 个 Token 给 to 这个 address function transfer(address to,uint256 tokens) external returns (bool success); // 得到 tokenOwner 授权给 spender 使用的 Token 剩余数量 function allowance(address tokenOwner,address spender) external view returns (uint256 remaining); // msg.sender 授权给 spender 可使用自己的 tokens 个 Token function approve(address spender,uint256 tokens) external returns (bool success); // 将 tokens 个 Token 从 from 转到 to function transferFrom(address from,address to,uint256 tokens) external returns (bool success); event Transfer( address indexed from, address indexed to, uint256 tokens ); event Approval( address indexed owner, address indexed spender, uint256 tokens ); }