本文已参与「新人创作礼」活动,一起开启掘金创作之路。
20.低级call,做函数选择器(不是是使用selector的方法)
uint写做uint256
21.delefatecall:委托调用(相当于运行在上下文:那么必须有一样的存储,顺序也要一样;如果你要增加变量,就需要从后面增加
在这里:注释和下面的东西的写法的结果都是一样的,下面这种写法能够保证避免写错大小写啥的.
注意的变量改变的是去调用的合约的变量,但是没有改变被调用合约的变量
22.合约工厂
把之前定义过的account,通过代码不断地创建起来,其中还可以通过花括号的方式把eth传进去
23.library库合约
library ArrayLib{
function find(uint[] storage arr,uint x)internal view returns(uint){
for (uint i =0;i<arr.length;i++){
if (arr[i] ==x){
return i;
}
}
revert("not found");
}
}
contract Test{
using ArrayLib for uint[]; //使用这个方法,可以做到在后面给arr这个数组有了find这个方法
function testMax(uint x ,uint y) external pure returns(uint){
// return Math.max(x,y);
return arr.find(2);
}
}
24.encode和encodepacked
encodepacked()会有一些压缩
\
25.通过智能合约验证签名
控制台etherumn.enable()打开metamask
自己先用地址做一个签名
下图最后一个函数比较:1.哈希后+签名 与 2.哈希后+模仿签名带头签名、哈希
可以算出来是同一个地址!!!
请看recover函数:(其实,相当于第一次hash并不重要,之所以做两次就是为了防止hash被破解)
1.上面这个哈希是用getmessage()做了一次哈希后又用下面这个函数拼接字符串做了哈希
function getEthSignedMessageHash(bytes32 _messageHash)
public
pure
returns (bytes32)
{
/*
Signature is produced by signing a keccak256 hash with the following format:
"\x19Ethereum Signed Message\n" + len(msg) + msg
*/
return
keccak256(
abi.encodePacked("\x19Ethereum Signed Message:\n32", _messageHash)
);
}
2.下面这个是用getmessage()做了一次哈希后又用我的钱包做了一次签名
function recover(bytes32 _ethSignedMessageHash,bytes memory _sig)
public pure returns(address){
(bytes32 r ,bytes32 s,uint8 v)=_split(_sig);
return ecrecover(_ethSignedMessageHash,v,r,s);
}
function _split(bytes memory _sig) internal pure returns(bytes32 r,bytes32 s,uint8 v){
assembly{
r:=mload(add(_sig,32))//最开始需要跳过32位
s:=mload(add(_sig,64))
v:=byte(0,mload(add(_sig,96)))
}
return (r,s,v);
}
26.私有变量比public更加省gas
27.自毁合约:
selfdestruct(payable(msg.sender))强制把钱送到一个地址,无论如何都会收到钱(不管合约有没有接收的函数)
自毁之后,函数的返回值都是0