1、随机数
pragma solidity >=0.4.22 <0.5.0;
contract random{
//生成100以内的随机数,msg.sender可以用别的全局变量替代
function test1() returns(uint){
return uint256(keccak256(now,msg.sender))%100;
}
uint256 win = 50;
//百分之50的概率为正(可以模拟骰子大小)
//通过win的调节可以调整正负的概率
function test2() returns(bool){
return uint256(keccak256(now,msg.sender))%100 <50;
}
}
2、静态library库
在Solidity中,与合约有些不同,Library不能处理ether。你可以把它当作一个EVM中的单例,又或者是一个部署一次后不再部署,然后能被做任意其它合约调用的公共代码。
这带来的一个显然好处是节省大量的gas(当然也可以减少重复代码对区块链带来的污染),因为代码不用一而再,再而三的部署,不同的合约可以依赖于同一个已部署的合约。
事实上,多个合约依赖于一个现存的代码,可以让营造一个更安全的环境。因为一方面这些方面有良好的代码审查(比如,Zepelin所做的伟大的工作),以及这些代码经过线上实际运行的验证。
pragma solidity >=0.4.22 <0.5.0;
library CounterLib {
//没有普通属性,只能有结构体
struct Counter { uint i; }
//Counter storage self 是默认的第一个函数
function incremented(Counter storage self,uint a) returns (uint) {
self.i = self.i + a;
return self.i;
}
}
contract CounterContract {
//引入库中的结构体
using CounterLib for CounterLib.Counter;
//定义
CounterLib.Counter counter;
function increment(uint a) view returns (uint) {
//通过定义的结构体调用库中的函数
counter.incremented(a);
return counter.i;
}
}
library SafeMathLib {
function times(uint a, uint b) returns (uint) {
uint c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function minus(uint a, uint b) returns (uint) {
assert(b <= a);
return a - b;
}
function plus(uint a, uint b) returns (uint) {
uint c = a + b;
assert(c>=a && c>=b);
return c;
}
function assert(bool assertion) private {
if (!assertion) throw;
}
}
contract libraryTest{
//引入库,uint作为第一个参数的类型
using SafeMathLib for uint;
function test(uint a,uint b) view returns(uint,uint){
//调用
uint jia = a.plus(b);
uint jian = a.minus(b);
return (jia,jian);
}
}
3、interface—接口的妙用
pragma solidity >=0.4.22 <0.5.0;
contract number1{
mapping(address => uint) addrMap1;
function setNum1(uint _num) public {
addrMap1[msg.sender] = _num;
}
function getNum(address _addr) public view returns(uint){
return addrMap1[_addr];
}
}
contract number2{
mapping(address => uint) addrMap2;
function setNum2(uint _num) public {
addrMap2[msg.sender] = _num;
}
function getNum(address _addr) public view returns(uint){
return addrMap2[_addr];
}
}
contract numberInterface{
function getNum(address _addr) public view returns(uint);
}
contract interfaceTest{
function test(address _addr) public view returns(uint,address){
//接口的使用,同一个接口接收了不同的合约地址,接口的参数为实现接口的合约的合约地址
numberInterface f = numberInterface(_addr);
return (f.getNum(msg.sender),msg.sender);
}
}
4、call函数——底层的调用
- 在一个合约里调用另一个合约——通过构造器构造实例调用,相当于外部调用
pragma solidity >=0.4.22 <0.5.0;
contract cat{
uint public c = 100;
function test(uint a) returns(uint){
c = a;
return c;
}
}
contract animal{
//定义一个cat合约
cat mycat;
//构造器,发布的时候需要填入cat合约地址
constructor(address _catAddr){
mycat = cat(_catAddr);
}
function getCat(uint a) returns(uint i){
return mycat.test(a);
}
}
- 在一个合约里调用另一个合约——通过call调用,地址调用
1、call是底层调用,只能返回true false;
contract cat{
uint public c = 100;
function test(uint a) returns(uint){
c = a;
//msg.sender为animal1合约地址
address addr = msg.sender;
return c;
}
}
contract animal1{
address catAddr;
constructor(address _catAddr){
catAddr = _catAddr;
}
function getCat(uint a) returns(bool){
return catAddr.call(bytes4(sha3("test(uint256)")),a);
}
}
- 在一个合约里调用另一个合约——通过delegatecall调用
1、通过delegatecall调用,相当于放入了本合约内部来使用,所以应用的全局变量要保持一致,如下uint public c
contract cat{
//这个值不会改变
uint public c = 100;
function test(uint a) returns(uint){
c = a;
//这个值不会改变
address addr = msg.sender;
return c;
}
}
contract animal2{
//会改变这个值
uint public c = 0;
address catAddr;
constructor(address _catAddr){
catAddr = _catAddr;
}
function getCat(uint a) returns(bool){
return catAddr.delegatecall(bytes4(sha3("test(uint256)")),a);
}
}
5、继承带参构造函数
1、继承时,默认的调用了父合约的空的构造函数
2、如果父合约的构造函数带参,则需要实例化父类的带参构造函数,
如下
pragma solidity >=0.4.22 <0.5.0;
contract father{
uint public money;
uint public height;
constructor(uint a,uint b){
money = a;
height = b;
}
}
contract son is father{
//实例化父合约的带参构造函数
constructor(uint a,uint b) father(a,b){
money = a;
height = b;
}
}
6、浅析事件event的用途
1、事件的触发
pragma solidity >=0.4.22 <0.5.0;
contract eventTest{
//事件定义
event senderLogger(address);
event valueLogger(uint);
//回调函数,给合约转账
function() payable{
senderLogger(msg.sender);
valueLogger(msg.value);
}
}
下图中的logs存储在区块头,from指的是转账地址,to是接收地址,topic指的是事件唯一标识,args是事件参数

image.png
2、事件的监听
待补充
7、合约嵌入内联汇编 solidity assembly
- 在solidity中执行汇编
- 优化效率,减少gas(不一定每次都能减少)
- 完成solidity完成不了的功能

image.png