智能合约笔记
2018-08-07 本文已影响1人
cowkeys
推荐一个入门小教程
记录:
1 错误 栈深溢出
CompilerError: Stack too deep, try removing local variables.
解决办法:原因是一个function里面的变量 数量不能超过(16),包括了入参和返回值。
2 货币单位
一个数字常量(字面量)后面跟随一个后缀wei, finney,szabo或ether,这个后缀就是货币单位。不同的单位可以转换。不含任何后缀的默认单位是wei。
不同的以太币单位转换关系如下:
1 ether == 10^3 finney == 1000 finney
1 ether == 10^6 szabo
1 ether == 10^18 wei
3 语法 using ... for ...
https://ethereum.stackexchange.com/questions/25829/meaning-of-using-safemath-for-uint256
4 web3.js 监听事件
(注意 用的是web3.js 1.0 和网上诸多教程 语法不一样)
Hello.sol:
//pragma关键字:版本申明。
//用来指示编译器将代码编译成特定版本,以免引起兼容性问题
//此处不支持0.4.0之前的编译器,也不支持0.5.0之后的编译器(条件为 ^)
pragma solidity ^0.4.0;
//contract关键字:合约申明
//和Java、PHP中的class类似
//此处是申明一个名为Hello的合约
contract Hello {
event doing(uint value);
//public: 函数访问属性(后续文章为详细阐述)
//returns (string): 定义返回值类型为string
function say(uint x, uint y) public returns (uint) {
//var n = bytes(name)
emit doing(x+y);
return x+y;
}
}
test.js
//设置web3连接
var Web3 = require('web3');
var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
//监听事件一定要用websocket [doc](https://web3js.readthedocs.io/en/1.0/web3.html)
web3.setProvider('ws://localhost:8546');
//读取合约
var fs = require('fs');
var contractCode = fs.readFileSync('Hello.sol').toString();
//编译合约代码
var solc = require('solc');
var compileCode = solc.compile(contractCode);
//获取合约abi和字节码
var abi = JSON.parse(compileCode.contracts[':Hello'].interface);
//var byteCode = compileCode.contracts[':Hello'].bytecode;
//合约对象 0x.. 为合约地址
var myContract = new web3.eth.Contract(abi,'0xD7309ac9B359b1F54CB81Bf7454732029937740E');
// 执行 node test.js 会一直监听事件
var event = myContract.events.doing(function (err,result) {
console.log("Event are as following:-------");
for(let key in result){
console.log(key + " : " + result[key]);
console.log(result["returnValues"]);
}
console.log("Event ending-------");
});
5 send 和 transfer 区别
https://blog.csdn.net/aaa19890808/article/details/79323243
地址的方法:send():用来向某个地址发送货币(单位为wei)
例子:向地址addr发送100wei
addr=0xqkwjhnckajhsdasdqwe
addr.send(100);
使用send()方法需要注意:
1.调用递归深度不能超过1024
2.gas不足会导致执行失败
3.使用这个方法需要检查成功与否
addr.transfer(10);
send和transfer的区别:
send方法和transfer很相似,但是比transfer更低级。如果send失败,当前的合约不会中断,也不会抛出异常,会返回一个false。使用send有一些风险:如果调用栈深度超过1024或是gas不够,所有的转让操作都会失败,为了更安全的以太币转移,如果用send就必须每次都要检查返回值,使用transfer方法会更好
6 view 和 pure 修饰符
view 修饰的函数 ,只能读取storage变量的值,不能写入。
pure 修饰的函数 , 不能对storage变量进行读写。
7 web3.js 中 call 和send 函数区别
- call is used for view and pure functions. It only runs on the local node, and won't create a transaction on the blockchain. 只能访问 view和pure函数
- send will create a transaction and change data on the blockchain. You'll need to use send for any functions that aren't view or pure.
8 web3.js 调用合约 交易
function createRandomZombie(name) {
$("#txStatus").text("Creating new zombie on the blockchain. This may take a while...");
return cryptoZombies.methods.createRandomZombie(name)
.send({ from: userAccount })
.on("receipt", function(receipt) {
$("#txStatus").text("Successfully created " + name + "!");
getZombiesByOwner(userAccount).then(displayZombies);
})
.on("error", function(error) {
$("#txStatus").text(error);
});
}
9 web3.js 监听事件
- Using indexed 只提醒给当某个地址
- event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
#+BEGIN_SRC
// Use `filter` to only fire this code when `_to` equals `userAccount`
cryptoZombies.events.Transfer({ filter: { _to: userAccount } })
.on("data", function(event) {
let data = event.returnValues;
// The current user just received a zombie!
// Do something here to update the UI to show it
}).on("error", console.error);
#+END_SRC
- Querying past events
#+BEGIN_SRC
cryptoZombies.getPastEvents("NewZombie", { fromBlock: 0, toBlock: "latest" })
.then(function(events) {
// `events` is an array of `event` objects that we can iterate, like we did above
// This code will get us a list of every zombie that was ever created
});
#+END_SRC