一步一步使用remix开发智能合约
最新版的remix(2017-8-3)只能使用在线开发了,已经没有离线版本了,并且好像在线版本要翻墙才能访问(自行解决).
1.打开remix
注意地址如果是https开头的,要换成http,否则就没法访问本地的http rpc了.
remix地址,打开以后会看到一个Ballot.sol文件,这是一个测试投票程序
2.打开本地的geth
本地的geth记得一定要开启rpc,下面是我自己的参数
ggeth.exe --datadir=d:/privnet --networkid 89120348581 --rpc --rpccorsdomain "*" --rpcapi "eth,admin,web3,net,debug"
--rpc 表示启动http rpc通道,否则只有本地ipc通道
--rpccorsdomain "*" 是允许跨域访问,否则http://ethereum.github.io/在对http://localhost:8545进行 http rpc通信时会被浏览器阻塞
--rpcapi "eth,admin,web3,net,debug" 由于安全起见,geth启动http rpc的时候是禁止了admin,debug等模块的,而我们想要通过remix来调试solidity就必须给与这些权限.
3. 配置remix
remix的Contract标签下的Environment不能是默认的Javascript VM,这样是没法运行智能合约的,必须选择Web3 Provider,另一个Injected Web3在我电脑上点了没有任何反应,不晓得什么原因.
具体如下图:
这时候浏览器会提示你链接http://localhost:8545 , 这时候确保你的geth已经启动,并且添加了--rpc参数,这里如果访问的是https://ethereum.github.io/browser-solidity,
还是会失败的,因为浏览器会禁止在https模式下去访问http地址.
如果成功,那么你就可以在Account下拉框中看到你自己的账户信息,如果没有看到那就是上面的某个步骤出错了.
4. 部署合约
点击Create按钮就可以创建合约了.
这时候最常见的错误有两个,一是账户没有解锁,那你就在geth console中调用personal.unlockAccount来解锁;二是余额不足.
当然还有一个就是如果你是在私链上,记得要启动miner,否则会一直不成功.
成功以后,就会看到下面的信息
会告诉你在花费了多少gas,合约的地址等信息.
还有就是下面会出现合约可以调用的函数,这时候你就可以切换上面的账户进行合约调用了.和普通的函数调用差不多.
就是要记得,这个是发生在区块链上的,每次调用都会花费以太币.
5.调试合约
调试也就是分步执行某个事务,这里的事务实际上就是一次合约调用,我这里使用的合约如下:
pragma solidity ^0.4.0;
contract Donation {
address owner;
event fundMoved(address _to, uint _amount);
modifier onlyowner { if (msg.sender == owner) _; }
address[] _giver;
uint[] _values;
function Donation() {
owner = msg.sender;
}
function donate() payable {
addGiver(msg.value);
}
function moveFund(address _to, uint _amount) onlyowner {
if (_amount <= this.balance) {
if (_to.send(this.balance)) {
fundMoved(_to, _amount);
} else {
throw;
}
} else {
throw;
}
}
function addGiver(uint _amount) internal {
_giver.push(msg.sender);
_values.push(_amount);
}
}
create 成功以后会出现两个调用按钮,donate和moveFund两个外部可调用函数. 其中donate是没有参数的,moveFund要有两个参数.
点击donate,会在区块链上执行该调用,结果如下:
Result: {
"blockHash": "0x05ff0a4b8680255fc2f8fd270ff29fc2658a4868bd4a834367e5292aa8c91235",
"blockNumber": 4471,
"contractAddress": null,
"cumulativeGasUsed": 88115,
"from": "0x1a9ec3b0b807464e6d3398a59d6b0a369bf422fa",
"gasUsed": 88115,
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"root": "0xf50ef054ab10044cb0ae253121abd8a971abaeb0b69d29bbf5d3ef97652292d7",
"to": "0xf77165817ad6e07cf32b16b2d6e64e3c85ca7ffc",
"transactionHash": "0xdf4d91c207cf8d7acee3c64add6a994039cf77d27e07e85633e7953e35e542e6",
"transactionIndex": 0
}
可以看到该事务发生在4471区块上,在该区块中的事务索引是0(因为是私链,肯定只会有这一个事务).
有了这些信息,我们就可以去调试这个调用
切换到Debugger模块:
如果按钮下面有一个The method debug_traceTransaction does not exist/is not available
,那是因为geth启动的时候没有添加参数
--rpcapi "eth,admin,web3,net,debug"
这时候我们就可以在代码中设置好断点,然后启动,程序就会停在断点处,我们可以在右侧的Solidity State中看到变量的变化.如果想要比较好的调试,还是需要懂一些evm的指令.
否则这样的调试感觉也意义不大,和js中按照语句调试不一样,这里主要是针对指令的调试,一句简单的_giver.push(msg.sender);
需要十几条指令.
当然以后随着remix的发展,调试应该会做的越来越好.