bit bytes 0x uint
bit 二进制位
byte 最小的存储单位 1 byte = 8bit (bytes1-32) bytes 不定长,引用类型
uint8 = 8 bit 最大值就是255 = 2^8-1 (uint(8-256))
0x 十六进制 一位 = 4bit 15 =2^4-1
一个数字或字母占一个字节,一个汉字占用3个字节
编码ASCII和BaseXX
- ASCII编码 7个bit位代表一个字符 0-127 每个数字对应一个字符也就是128个字符
[0, 31] 以及 127 (del) 这 33 个属于不可打印的控制字符才有了base64 MIME多媒体传递数据
- Base32编码 A-Z(26) 2-7(6) 空白用= padding 5个bit代表一个字符 0-31 每个数字代表要给字符也就是32个字符
- Base64编码 A-Za-z(52) 0-9(10) + / 6个bit代表一个字符0-63 每个数字代表要给字符也就是64个字符
算法就是3个字节(3*8bit)转成4个base64字符(可打印的字符),不是3的倍数,用=号补充
ASCII对应的对应的字符 转成bit 然后转成base64显示出来
3*8bit=6bit(base64字符)*4
- Base58 o0 1i +/ 去掉
1. encode 标准的对参数abi编码
abi.encode(address(0x630959E5aE57D1165c29B5aDC2F77C2bB8B730a0),127)
000000000000000000000000630959e5ae57d1165c29b5adc2f77c2bb8b730a0
000000000000000000000000000000000000000000000000000000000000007f
生成的abi会自动填充到32个byte 就是64个十六进制位
2. encodePacked
abi.encodePacked(address(0x630959E5aE57D1165c29B5aDC2F77C2bB8B730a0),uint8(127));
0x630959e5ae57d1165c29b5adc2f77c2bb8b730a0
7f
不会填充,紧编码数据
3. decode对编码后的数据解码
abi.encode(“a”,“b”)
abi.decode(data, (string, string))
4. encodeWithSelector 对方法keccak256和参数encode并拼接到一起返回
abi.encodeWithSelector(bytes4(keccak256(“set(uint256)”)),number)
5. encodeWithSignature 相当于上面的简写
abi.encodeWithSignature(“set(uint256)”,number)
6. Storage Proxy中的属性要和impl的一致
7. delegatecall 调用编码后的方法 修改proxy中的值 读取的时候是proxy中的值
8. call 调用编码后的方法 修改impl中的值 staticcall-只能读取值,不能写值
// SPDX-License-Identifier: MIT pragma solidity ^0.8; contract BytesStudy{ uint public setX; bytes1 a2 = '1'; bytes5 hh = 0xffffffffff; bytes2 b = '11'; bytes3 c = 0xffffff; bytes32 d = '01234567890123456789012345678900'; function test() public view returns (bytes4, bytes1, bytes1, bytes1, bytes1,bytes1){ bytes4 a = 0x001122FF; return (a, a[0], a[1], a[2], a[3],a2); } function concat(string memory _a, string memory _b) public pure returns (string memory) { return string(abi.encodePacked(_a, _b)); } //生成的abi需要填充到32个byte 就是64个十六进制位 function testEncode() public pure returns (bytes memory){ return abi.encode("a","b"); } // function decode(bytes memory data) public pure returns (string memory _str1, string memory _str2) { (_str1, _str2) = abi.decode(data, (string, string)); } //000000000000000000000000630959e5ae57d1165c29b5adc2f77c2bb8b730a0 //000000000000000000000000000000000000000000000000000000000000007f function testEncode2() public pure returns (bytes memory){ return abi.encode(address(0x630959E5aE57D1165c29B5aDC2F77C2bB8B730a0),127); } //0xb63e800d000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000500e5eb0cf12736f237604bb90ee996a24def620000000000000000000000000aeb79c89bd801348da200c73533908562a1d726e00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000 //去掉前面的方法id(0x+4个bytes(8个16进制位))就是参数值000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000500e5eb0cf12736f237604bb90ee996a24def620000000000000000000000000aeb79c89bd801348da200c73533908562a1d726e00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000 function test4(bytes memory d) public pure returns (address[] memory,uint256,address,bytes memory,address,address,uint256,address){ return abi.decode(d, (address[],uint256,address,bytes,address,address,uint256,address)); } //不会填充到64位 uint8=8bit = 1bytes = 2十六进制位 //0x630959e5ae57d1165c29b5adc2f77c2bb8b730a0 //7f function testEncodePacked2() public pure returns (bytes memory){ return abi.encodePacked(address(0x630959E5aE57D1165c29B5aDC2F77C2bB8B730a0),uint8(127)); } function testEncodePacked() public pure returns (bytes memory){ return abi.encodePacked("a","b"); } //方法名和参数的abi编码1 //传入10返回 //0x60fe47b1 //000000000000000000000000000000000000000000000000000000000000000a function testEncodeWithSelector(uint number) public pure returns (bytes memory){ return abi.encodeWithSelector(bytes4(keccak256("set(uint256)")),number); } function set(uint x) public { setX = x; } //方法名和参数的abi编码2 function testEncodeWithSignature(uint number) public pure returns (bytes memory){ return abi.encodeWithSignature("set(uint256)",number); } } contract MyProxy { uint public setX; //可以修改MyProxy-setX值 //0x60fe47b1 //000000000000000000000000000000000000000000000000000000000000000a function doFunction(address _address,bytes calldata _calldata ) public returns (bool){ (bool success,) = _address.delegatecall(_calldata); require(success); return true; } //修改的是BytesStudy-setX值 function doFunction2(address _address,bytes calldata _calldata ) public returns (bool){ (bool success,) = _address.call(_calldata); require(success); return true; } } contract TestPayable { uint x; uint y; fallback() external payable { x = 1; y = msg.value; } receive() external payable { x = 2; y = msg.value; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8; contract TestPayable { event Log(string methodName,uint _x,uint _y); uint x; uint y; //调用没有对应的方法时候的回调 fallback() external payable { x = 1; y = msg.value; emit Log("fallback",x,y); } //接受到eth的回调 receive() external payable { x = 2; y = msg.value; emit Log("receive",x,y); } function clearXY() public returns (uint) { x = 0; y = 0; emit Log("clearXY",x,y); return 0; } function setXY(uint _x,uint _y) public { x = _x; y = _y; emit Log("setXY",x,y); } function getValue() public pure returns (uint) { return 0; } function getValue2() public pure returns (uint,uint) { return (0,1); } } contract TestSender { event Log(string name,address _addre); //msg.sender调用这个合约的地址(包括普通地址或者合约地址) function testSender() public { emit Log("TestSender",msg.sender); } } contract TestProxy { event Log(string name,address _addre); event LogBool(string name,bool isOK, bytes dt); // 测试msg.sender function callTestSender(TestSender ts) public { emit Log("TestProxy",msg.sender); ts.testSender(); } // 写的方法有1个返回值 function callTestPayable(address _address) public returns (bool) { (bool success,bytes memory returnData) = _address.delegatecall(abi.encodeWithSignature("clearXY()")); emit LogBool("callTestPayable-clearXY",success,returnData); require(success); return true; } // 读的方法有1个返回值 function callTestPayable2(address _address) public returns (bool) { (bool success,bytes memory returnData) = _address.delegatecall(abi.encodeWithSignature("getValue()")); emit LogBool("callTestPayable2-getValue",success,returnData); require(success); return true; } //没有对应的调用方法 function callTestPayableNo(address _address) public returns (bool) { (bool success,) = _address.delegatecall(abi.encodeWithSignature("clearXYZ()")); emit LogBool("callTestPayableNo-clearXYZ",success,'aaaa'); require(success); return true; } // 读的方法有1个返回值 //0000000000000000000000000000000000000000000000000000000000000000 //0000000000000000000000000000000000000000000000000000000000000001 function callTestPayable3(address _address) public returns (bool) { (bool success,bytes memory returnData) = _address.delegatecall(abi.encodeWithSignature("getValue2()")); emit LogBool("callTestPayable3-getValue2",success,returnData); require(success); return true; } }
9. 实例代码App
MyApp
// SPDX-License-Identifier: MIT pragma solidity ^0.8; //属性存储插槽slot中,每个solt顺序合约A和aProxy一致,否则会报错 //定义不同的Storage来存储属性值 让合约A,aProxy继承来统一插槽 //用户信息 contract MyAppStorage { struct User{ uint age; uint sex; bool isMember; } mapping (address => User) public users; bool public isOpen; string public appName; } contract OwnableStorage { address public owner; constructor() { owner = msg.sender; } event OwnerUpdate(address _prevOwner, address _newOwner); modifier onlyOwner { require(msg.sender == owner,"only owner"); _; } function transferOwnership(address _newOwner) public onlyOwner { require(_newOwner != owner, "Cannot transfer to yourself"); owner = _newOwner; } } contract ProxyStorage { /** * Current contract to which we are proxing */ address public currentContract; } contract Storage is MyAppStorage,OwnableStorage,ProxyStorage { } interface IMyApp{ event RegisterUser( address indexed _caller, address indexed _deployer ); event eOpen( bool indexed rIsOpen ); event logName(string name); function updateOpen(bool _isOpen) external; } contract MyApp is Storage,IMyApp{ function initialize() external { appName = "AppTest"; } modifier onlyOpen { require(isOpen,"only open"); _; } // 测试阶段用public,正式环境用external function registerUser(address beneficiary) public onlyOpen{ require(beneficiary != address(0), "invalid address"); require(users[beneficiary].isMember == false, "address is already register"); User storage user = users[beneficiary]; user.isMember = true; emit RegisterUser(msg.sender, beneficiary); } function updateOpen(bool _isOpen) override public onlyOwner{ isOpen = _isOpen; emit eOpen(isOpen); } }
proxy
// SPDX-License-Identifier: MIT pragma solidity ^0.8; //用户信息 contract MyAppStorage { struct User{ uint age; uint sex; bool isMember; } mapping (address => User) public users; bool public isOpen; string public appName; } contract OwnableStorage { address public owner; constructor() { owner = msg.sender; } event OwnerUpdate(address _prevOwner, address _newOwner); modifier onlyOwner { require(msg.sender == owner,"only owner"); _; } function transferOwnership(address _newOwner) public onlyOwner { require(_newOwner != owner, "Cannot transfer to yourself"); owner = _newOwner; } } contract ProxyStorage { /** * Current contract to which we are proxing */ address public currentContract; } contract Storage is MyAppStorage,OwnableStorage,ProxyStorage { } contract DelegateProxy { /** * @dev Performs a delegatecall and returns whatever the delegatecall returned (entire context execution will return!) * @param _dst Destination address to perform the delegatecall * @param _calldata Calldata for the delegatecall */ function delegatedFwd(address _dst, bytes memory _calldata) internal { require(isContract(_dst)); assembly { let result := delegatecall(gas(), _dst, add(_calldata, 0x20), mload(_calldata), 0, 0) let size := returndatasize() let ptr := mload(0x40) returndatacopy(ptr, 0, size) // revert instead of invalid() bc if the underlying call failed with invalid() it already wasted gas. // if the call returned error data, forward it switch result case 0 { revert(ptr, size) } default { return(ptr, size) } } } function isContract(address _target) view internal returns (bool) { uint256 size; assembly { size := extcodesize(_target) } return size > 0; } } contract Proxy is Storage, DelegateProxy { event UpgradeE(address indexed newContract); event Fallback(bytes msgData); function Upgrade(address _proxy) public onlyOwner { currentContract = _proxy; } fallback() external payable { emit Fallback(msg.data); require(isContract(currentContract),"error currentContract"); delegatedFwd(currentContract,msg.data); } receive() external payable { } } contract MyAppProxy is Proxy {}