Bernau

7.15-8.24学习记录日记

几个方向

ABI

(Address)

插槽(Slot)

Gas 交易费用

数据结构

事件(Event)

升级合约

签名/钱包

ERC-6551

跨链 | ​ChainLink

EVM

IPFS

DEFI

ERC-​20/ERC-721

功能模块

项目与应用

MetaMask

ChatGPT 实践​

联系我 dm me

Simple Telegram Icon
Simple Twitter Icon

日记仅作为记录学习日常,无任何建议

学习出自ThingChain老师

如有错误请电报或推特dm我

7.15日记录

  • 调用合约方法的时候,需要对被调用的方法和参数进行encode,其过程比较繁琐。此时,Solidity就封装了三​个encode方法


// SPDX-License-Identifier: GPL-3.0


pragma solidity >=0.7.0 <0.9.0;


contract A {

event Message(uint256 num, string message);

event Response(bool success, bytes data);


function getBFunctionBytes4() public pure returns (bytes4) {

return bytes4(keccak256("bFunction(uint256,string)"));

}


function getParamsBytes(uint256 _num, string calldata _message)

public

pure

returns (bytes memory)

{

return abi.encode(_num, _message);

}


function callBFuncton(address _bAddress, bytes calldata _data)

public

returns (bool)

{

(bool success, ) = _bAddress.call(_data);

return success;

}


function callBFuncton(

address _bAddress,

uint256 _num,

string memory _message

) public returns (bool) {

bytes4 sig = bytes4(keccak256("bFunction(uint256,string)"));

/**

//1、encodeWithSignature

(bool success, ) = _bAddress.call(

abi.encodeWithSignature("bFunction(uint256,string)", _num,_message)

);

*/

/*

//2、encodePacked


bytes memory _bNum = abi.encode(_num);

bytes memory _bMessage = abi.encode(_message);


(bool success, ) = _bAddress.call(

abi.encodePacked(sig, _bNum,_bMessage)

);

*/


//3、encodeWithSelector

(bool success, bytes memory data) = _bAddress.call(

abi.encodeWithSelector(sig, _num, _message)

);

emit Response(success, data);


/*

//4、instance.callfunction

B bContract = B(_bAddress);

(uint256 num ,string memory message) = bContract.bFunction(_num,_message);

emit Message(num ,message);

*/

return true;

}

}


contract B {

uint256 public num;

string public message;


function bFunction(uint256 _num, string memory _message)

public

returns (uint256, string memory)

{

num = _num;

message = _message;

return (num, message);

}


fallback() external {}

}




7.16日记录

【Solidity进阶系列】 | ABI | 使用Encodepacked方法注意事项

  • encodepacked方法能省Gas
  • encodepacked建议不要使用动态变量类型传参,例如bytes、string或数组。可​以使用uint和address传参


// SPDX-License-Identifier: GPL-3.0


pragma solidity >=0.7.0 <0.9.0;


contract A {


function callBFuncton(address _bAddress, uint256 _num,address _message) public returns(bool)​{

//2、encodePacked

bytes4 sig = bytes4(keccak256("bFunction(uint256,address)"));

bytes memory _bNum = abi.encode(_num);

bytes memory _bMessage = abi.encode(_message);

(bool success, ) = _bAddress.call(

abi.encodePacked(sig, _bNum,_bMessage)

);

return success;

}


function encode(string memory _message) public pure returns(bytes memory message){

return abi.encode(uint256(1), _message,"world");

}


function encodePacked(string memory _message) public pure returns(bytes memory message){

return abi.encodePacked(uint256(1),abi.encode(_message),abi.encode("world"));

}


function encodePacked() public pure returns(bytes memory message){

return abi.encodePacked(uint256(1),"hellow","orld");

}

}


contract B {

uint256 public num;

address public message;

event ReceiveMessage(uint256 num,address message);


function bFunction(uint256 _num, address _message) public returns(uint256 ,address ){

emit ReceiveMessage(_num,_message);

num = _num;

message = _message;

return (num, message);

}

}



使用abi.encodepacked 不要传两个字符串,(字符串 数组 字节),否则会出现穿的字符串不一样但是输出结果​一样,可以传整型+字符串

传入整型+地址 可以完成A合约调用B合约方法

传入的字符串就会导致A调用B合约 但是输出的是空的

7.17日记

今天测试同区块自定义金额开盘买入脚本

7.18日记录

Address | Call 方法

  • Call方法可以转账,它具备transfer、send方法同样的功能
  • Call方法可以同时转账与调用合约的方法

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.19;

import "hardhat/console.sol";


contract CallExample {

//address payable 拥有transfer方法

function transfer(address payable _to) public payable {

_to.transfer(msg.value);

}


//address payable 拥有send方法

function send(address payable _to) public payable {

bool isSend = _to.send(msg.value);

require(isSend, "Send fail");

}


//address不需要payable修改,都可以调用Call方法

//_to如果是合约地址,必须在_to合约里面添加 receive或fallback方法。

//为什么要这么做呢?如果把ETH转到不能提现的合约,那么该ETH就永久消失

function call(address _to) public payable {

(bool sent, ) = _to.call{value: msg.value}("");

require(sent, "Send fail");

}


//_to是EOA钱包地址,("") calldata将被忽略掉

function callWithData(address _to) public payable {

(bool sent, ) = _to.call{value: msg.value}(abi.encodeWithSignature("increaseNumber(uint256)", ​10));

require(sent, "Send fail");

}

}


contract ReceiveEther {


receive() external payable {}


fallback() external payable{}


function increaseNumber(uint256 num) public pure returns (uint256) {

return ++num;

}

}

由合约contract CallExample 中调用call方法传入1ether传到合约​contract ReceiveEther中可以成功,因为该合约中写了receive()或​者fallback() 方法,不写的话 用call方法不可传入,下图是传入成功​案例和失败案例

其次用tranfer方法给钱包地址或者合约地址转账时,要给地​址address 加payable修饰符,不然没办法调用此功能