一、solidity中的特殊变量
solidity中有一些特殊变量,不需要定义即可以使用,其实是EVM中的内置变量,对应的映射如下所示:
- block.blockhash(uint blockNumber) returns (bytes32): hash of the given block - only works for 256 most recent, excluding current, blocks - deprecated in version 0.4.22 and replaced by blockhash(uint blockNumber).
- block.coinbase (address): current block miner’s address
- block.difficulty (uint): current block difficulty
- block.gaslimit (uint): current block gaslimit
- block.number (uint): current block number
- block.timestamp (uint): current block timestamp as seconds since unix epoch
- gasleft() returns (uint256): remaining gas
- msg.data (bytes): complete calldata
- msg.gas (uint): remaining gas - deprecated in version 0.4.21 and to be replaced by gasleft()
- msg.sender (address): sender of the message (current call)
- msg.sig (bytes4): first four bytes of the calldata (i.e. function identifier)
- msg.value (uint): number of wei sent with the message
- now (uint): current block timestamp (alias for block.timestamp)
- tx.gasprice (uint): gas price of the transaction
- tx.origin (address): sender of the transaction (full call chain)
二、solidity中的函数修饰符
Solidity 0.4.16 引入了 view 和 constant 修饰符,用来描述函数的属性,除了这几个,还有internal、external、private、public、payable。
- private: 私有函数。内部访问,外部无法访问,子类无法继承。
- public: 公共函数。内部正常访问,外部正常访问, 子类可继承。
- internal: 内部函数。内部访问,外部无法访问,子类可以继承。
external: 外部函数。内部不能访问, 外部正常访问, 子类可继承。
view: 没有改变state的函数声明为view
note:
constant on functions used to be an alias to view, but this was dropped in version 0.5.0.
Getter methods are marked viewspure: 即不读state也不改变state
pragma solidity ^0.4.19;
contract Test {
uint id = 0;
function get_id() public pure returns(uint) {
return id;
}
}
这里的pure函数读取id,id存在于state中,sol compiler会报error,改成constant或者view即可通过。
test.sol:7:16: Error: Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
return id;
- payable: 专用于接收value,修改smart contract账户的balance。
三、smart contract对Ether的处理
标记有payable的函数才能对msg.value进行处理,但是这其实并不是由solidity本身决定的,而是通过vm和solidity一起作用的。正如parity中实现,在params.value != 0
的时候,call一个非payable的函数或者create contract的时候,evm返回revert。如果vm不返回revert,那么kernel在启动vm之前由于已经将value转到params.address中,这笔钱就花冤枉了。在call一个payable函数的时候,如果没有其他错误,返回EvmSuccess。
note: 网上有说在call一个deposit payable函数的时候,已经将value转到了合约账户中,这个动作就是在kernel中完成的。所以通过deposit函数能拿到(address(this).balance)合约账户更新后的balance
这是我的一个测试用例:
pragma solidity ^0.4.15;
contract Test {
uint id = 99;
function get_id() public constant returns(uint) {
return id;
}
function get_money() public constant returns(uint) {
return address(this).balance;
}
}