solidity 基础知识(一) 报错控制的相关知识点 用于检查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 contract error{ function testrequire (uint i) public pure{ require(i<=10 ,"i>10" ); } function testrevert (uint i) public pure{ if (i>10 ){ revert("i>10" ); }} uint public num=123 ; function testassert () public view{ assert(num==123 ); } function foo () public{ num+=1 ; } error Myerror (address caller,uint i) ; function testcustom (uint i) public view{ if (i>10 ){ revert Myerror (msg.sender,i) ; } } }
函数修改器知识 修饰器(modifier)是 solidity 特有的语法,它就像钢铁侠的智能盔甲,有特定功能,也可以控制访问权限。modifier 的主要使用场景是运行函数前的检查,例如地址,变量,余额等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 contract functionmodifier{ bool public paused; uint public count; function setPause (bool _paused) external{ paused=_paused; } modifier whenpaused () { require(!paused,"paused" ); _; } function inc () external whenpaused{ count+=1 ; } function dec () external whenpaused{ count-=1 ; } modifier cap (uint x) { require(x<100 ,"x>=100" ); _; } function incBy (uint x) external whenpaused cap (x) { count+=x; } modifier sandwich () { count +=10 ; _; count *=2 ; } function foo () external sandwich{ count+=1 ; } }
构造函数 构造函数(constructor)是一种特殊的函数,每个合约可以定义一个,并在部署合约的时候自动运行一次。它可以用来初始化合约的一些参数,例如初始化合约的 owner 地址
1 2 3 4 5 6 7 8 contract Constructor{ address public owner; uint public x; constructor(uint _x){ owner = msg.sender; x = _x; } }
总结1 前面内容的合成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 pragma solidity^0.8 .0 ; contract Ownable{ address public owner; constructor(){ owner = msg.sender; } modifier onlyOwnable () { require(msg.sender==owner ,"not owner" ); _; } function setowner (address _newOwner) external onlyOwnable{ require(_newOwner!=address(0 ),"invalid address" ); owner=_newOwner; } function onlyOwner () external onlyOwnable{ } function anyone () external{ } }
returns的写法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 contract functionoutput{ function returnMany () public pure returns (uint , bool ) { return (1 ,true ); } function named () public pure returns (uint x,bool b) { return (1 ,true ); } function assigned () public pure returns (uint x,bool b) { x=1 ;b=true ; } function destructing () public pure{ uint x;bool b; ( x , b )=returnMany(); (, b)=returnMany(); } }
数组的知识点 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 contract Array{ uint[]public nums=[1 ,2 ,3 ]; uint[3 ]public numsfixed=[4 ,5 ,6 ]; uint public x; uint public len; function examples () external{ nums.push(4 ); x=nums[1 ]; nums[2 ]=777 ; delete nums[1 ]; nums.pop(); len=nums.length; uint []memory a=new uint[](5 ); a[1 ]=123 ; } function returnarray () external view returns (uint[] memory) { return nums; } }
数组的删除函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 contract ArrayShift{ uint []public arr; function example () public { arr=[1 ,2 ,3 ]; delete arr[1 ]; } function remove (uint _index) public{ require(_index<arr.length,"index out of bound" ); for (uint i=_index;i<arr.length-1 ;i++){ arr[i]=arr[i+1 ]; } arr.pop(); } }
映射 1 2 3 4 5 6 7 8 9 10 11 12 13 14 contract Mapping{ uint bal; uint bal2; mapping(address =>uint)public balances; mapping(address=>mapping(address=>bool ))public isFriend; function examples () external{ balances[msg.sender]=123 ; bal =balances[msg.sender]; bal2=balances[address(1 )]; balances[msg.sender]+=456 ; delete balances[msg.sender]; isFriend[msg.sender][address(this)]=true ; } }
映射与数组的结合,高价值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 contract iterableMapping{ mapping(address=>uint)public balances; mapping(address=>bool )public inserted; address[]public keys; function set (address _key,uint _val) external{ balances[_key]=_val; if (!inserted[_key]){ inserted[_key]=true ; keys.push(_key); } } function getsize () external view returns (uint) { return keys.length; } function first () external view returns (uint) { return balances[keys[0 ]]; } function last () external view returns (uint) { return balances[keys[keys.length-1 ]]; } function get (uint i) external view returns (uint) { return balances[keys[i]]; }
结构体的定义方法与数组组合 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 contract Struct{ struct Car { string model; uint year; address owner; } Car public car; Car[] public cars; mapping(address =>Car[])public carsByOwner; function examples () external{ Car memory toyota=Car("Toyota" ,1990 ,msg.sender); Car memory lambo=Car({year:1980 ,model:"Lamborghini" ,owner:msg.sender}); Car memory tesla; tesla.model="Tesla" ; tesla.year=2010 ; tesla.owner=msg.sender; cars.push(toyota); cars.push(lambo); cars.push(tesla); cars.push(Car("Ferrari" ,2020 ,msg.sender)); Car storage _car=cars[0 ]; _car.year=1999 ; delete _car.owner; delete cars[1 ]; } }
枚举的用法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 contract Enum{ enum Status { None, Pending, Shipped, Completed, Rejected, Canceled } Status public status; struct Order { address buyer; Status status; } Order[]public orders; function get (Status _status) external returns (Status) { status=_status; return status; } function ship () external{ status=Status.Shipped; } function reset () external{ delete status; } }
通过内联汇编部署合约(懵点) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 contract TextContract1{ address public owner=msg.sender; function setOwner (address _owner) public{ require(msg.sender==owner,"not owner" ); owner=_owner; } } contract TestContract2{ address public owner=msg.sender; uint public value=msg.value; uint public x; uint public y; constructor(uint _x,uint _y){ x=_x; y=_y; } } contract Proxy{ event Deploy (address) ; function deploy (bytes memory _code) external payable returns (address addr) { assembly{ addr :=create(callvalue(),add(_code,0x20 ),mload(_code)) } require(addr!=address(0 ),"deploy failed" ); emit Deploy (addr) ; } function execute (address _target,bytes memory _date) external payable{ (bool success, )=_target.call{value:msg.value}(_date); require(success,"failed" ); } } contract Helper{ function getBytecode1 () external pure returns (bytes memory) { bytes memory bytecode=type(TestContract1).creationCode; return bytecode; 没有构造函数时用此方法获得bytecode; } function getBytecode2 (uint _x,uint _y) external pure returns (bytes memory) { bytes memory bytecode=type(TestContract2).creationCode; return abi.encodePacked(bytecode,abi.encode(_x,_y)); } function getCalldate (address _owner) external pure returns (bytes memory) { return abi.encodeWithSignature("setOwner(address)" ,_owner); } }
用create2来构造函数(可提前预测生成的地址) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 pragma solidity ^0.8 .0 ; contract DeployWithCreate2{ address public owner; constructor(address _owner){ owner=_owner; } } contract Create2Factory{ event Deploy (address addr) ; function deploy (uint _salt) external{ DeployWithCreate2 _contract=new DeployWithCreate2{ salt:bytes32(_salt) }(msg.sender); emit Deploy (address(_contract)) ; } function getAddress (bytes memory bytecode,uint _salt) public view returns (address) { bytes32 hash=keccak256(abi.encodePacked( bytes1(0xff ),address(this),_salt,keccak256(bytecode) )); return address(uint160(uint(hash))); } function getBytecode (address _owner) public pure returns (bytes memory) { bytes memory bytecode=type(DeployWithCreate2).creationCode; return abi.encodePacked(bytecode,abi.encode(_owner)); } }