第三课
如果solidity的library中的函数通过internal修饰这样的函数是不能通过library.function
这种方式调用,只能通过如下方式调用。
using library for uint256
uint a;
a.function(arg)
EVM中是没有!=
对应的操作码
通过
if (a == 0) {}
比
require(a != 0, message)
这种方式要节约gas。
merkle trie
假设hash01是hash0和hash1的根节点,则hash0在hash1的左侧位置
Address库的isContract函数
如果在合约的创建过程中调用该函数判断该账户是否为合约账户的时会返回不是一个合约账户
。
如果合约1在构造函数中去创建合约2,那么在合约2的构造函数中通过msg.sender.isContract()
是判断不出来是否为合约账户的。因为这时合约1自己还没有完成合约的创建。
防止充入
参见openzeppelin的ReentranceGuard.sol。
不要采取进入函数前修改storage变量,执行函数结束前再次修改回刚才修改的storage变量。
如果在一个合约中两个函数func1和func2都用nonReentrant修饰则会导致func1不能调用func2。
ERC(Ethereum Request for Comment)与EIP(Ethereum Improvement Proposal)
在ERC项目中建立issue来讨论,如果被采纳将会进入EIP。
solidity的memory
solidity的memory前四个word是预留的, 前两个word(即64字节)是用来作hash运算的
,第三个word是memory的已使用的内存大小,这个值也是未使用的memory的起始位置。
产生message call的五种方式
call:
callcode:
delegatecall:
new(create):
staticcall: 没有全局函数,但是内联汇编可以用 。不会修改状态。
openzeppelin的introspection
用于判断一个合约是否包含某个function
event中的indexed
如果一个event中某个参数被设置为indexed话,通过jsonrpc或者web3js调用filter将某一个参数的具体值的所有事件都找出来。具体参见eth_newFilter和这篇文章。
使用truffle的web3.eth.filter来监听event
假设有
event Deposited(address indexed payee, uint256 weiAmount);
使用如下代码监听该event
//将address转换为log中可以匹配的address即padded address
function toPaddedAddress(address) {
if (address.startsWith("0x"))
address = address.substring(2);
return '0x000000000000000000000000' + address;
}
const filter = web3.eth.filter({
fromBlock: 0, //指定起始块
toBlock: 'latest',
address: contract.address, //如果没有该address则匹配所有合约的满足下面topics条件的event
topics: [
web3.sha3("Deposited(address,uint256)"),
toPaddedAddress(accounts[1]) //这个就是indexed的
]
});
filter.watch((error, result) => {
console.log(error, result);
})
Ownable.sol中的renounceOwnership
该函数为放弃合约中的归属权,应用在当合约创建后并所有参数被敲定后为了使合约只按照逻辑被操纵这时可以放弃归属权。
合约中private修饰的变量前面加_
前缀
合约中的private和internal
如果是Library中的函数通过internal修饰可以通过using for被合约中的变量调用。如果是Contract中函数通过internal修饰,可以被本合约函数调用,也可以被继承该合约的合约中的函数调用。如果是被private修饰则只能被本合约
函数调用。