function pop() public virtual returns(string memory){//需要被继承的合约要加virtual return"A"; } function hip()public virtual returns(string memory){ return"A"; } function Aa()public pure returns(string memory){ return"A"; } } contract B is A{ function pop() public virtual override returns(string memory){//加继承的函数加override return"B"; } function hip()public virtual override returns(string memory){ return"B"; } function Bb()public pure returns(string memory){ return"B"; } } contract C is A, B{//多线继承,最基础的放在最前面,然后依次排列 function pop()public pure override(A,B)returns(string memory){ return"C"; } function hip()public pure override(A,B)returns(string memory){ return"C"; } }
contract visibility{ uint private x=0; uint internal y=1; uint public z=2; function privateFunc()private pure returns(uint){ return0; } function internalFunc()internal pure returns(uint){ return100; } function publicFunc()public pure returns(uint){ return200; } function externalFunc()external pure returns(uint){ return300; } function examples()external view{ x+y+z; privateFunc(); internalFunc(); publicFunc(); this.externalFunc();//可以通过这样来访问外部函数。原理:先到合约外部在到内部从而访问external函数。 } }
不可变量
不可变量immutable用的时候必须赋值
1 2 3 4 5 6 7 8 9 10 11
contract Immutable{ address public immutable owner = msg.sender;//像定义常量一样节约gas费,同样owner永不可变 // constructor(){ // owner=msg.sender;可在构建函数时赋值 //} uint public x; function foo()external{ require (msg.sender == owner); x+=1; } }
/* 1.直接调用发生的变化 A calls B,sends 100 wei B calls C,sends 50wei A --->B --->C msg.sender=B msg.value=50 execute code on C state variables use ETH in C 2.委托调用发生的变化 A calls B,sends 100 wei Bdelegatecall C A--->B--->C msg.sender=A msg.value=100 execute code on B state variables use ETH in B */ contract TestDelegatecall{//测试合约 uint public num; address public sender; uint public value; function setVars(uint _num)external payable{ num=_num; sender=msg.sender; value=msg.value; } } //委托调用合约,只改变委托合约的变量,不改变测试合约变量,通过测试合约改变了委托合约中的状态变量 contract DelegateCall{ uint public num; address public sender; uint public value; function setVars(address _test,uint _num)external payable{ // _test.delegatecall( // abi.encodeWithSignature("setVars(uint256)",_num) // ); _test.delegatecall( (bool success ,bytes memory data)= abi.encodeWithSelect(TestDelegatecall.setVars.selector ,_num) ); require(success."delegatecall failed"); } }
用new来创建合约
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
contract Account{ address public bank; address public owner; constructor(address _owner)payable{ bank=msg.sender; owner=_owner; } } contract AccountFactory{ Account[]public accounts; function createAccount(address _owner)external payable{ Account account=new Account{value:111}(_owner);//创建合约 accounts.push(account);//将合约添入数组 } }
/* 四步骤: 1.message to sign 2.hash(message) 3.sign(hash(message),private key) | offchain(链下完成) 4.ecrecover(hash(message),signature)==signer 恢复签名,得出签名人的地址 */ contract VerifySig{//签名的验证 function verify(address _signer,string memory _message,bytes memory _sig) external pure returns(bool)//_sig 签名结果 { bytes32 messageHash=getMessageHash(_message); bytes32 ethSignedMessageHash=getEthSignedMessageHash(messageHash); return recover(ethSignedMessageHash,_sig)==_signer; } function getMessageHash(string memory _message)public pure returns(bytes32){ return keccak256(abi.encodePacked(_message));//第一次加密 } function getEthSignedMessageHash(bytes32 _messageHash)public pure returns(bytes32){//第二次加密 return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32",_messageHash));//两次哈希且增加字符串更安全 }
function toEthSignedMessageHash(bytes memory s) internal pure returns(bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", toString(s.length), s)); }
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns(bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } 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)//32+32+1=65位的长度 {//将加密信息分割成r s v require(_sig.length==65,"invalid length"); assembly {//用内联汇编进行分割_sig(只能) r:=mload(add(_sig,32)) s:=mload(add(_sig,64)) v:=byte(0,mload(add(_sig,96))) } } function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) { return"0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } returnstring(buffer);} function get(string memory _message)public pure returns(bytes memory){ //return keccak256(abi.encodePacked(_message));//第一次加密 return abi.encodePacked(_message); return keccak256(abi.) }}