solidity实现账户地址向合约账户转账
一个合约最多有一个 receive 函数, 声明函数为: receive() external payable { … } 不需要 function 关键字,也没有参数和返回值并且必须是 external 可见性和 payable 修饰. 它可以是 virtual 的,可以被重载也可以有 修改器modifier 。 在对合约没有任何附加数据调用(通常是对合约转账)是会执行 receive 函数. 例如 通过 .send() or .transfer() 如果 receive 函数不存在, 但是有payable 的 fallback 回退函数 那么在进行纯以太转账时,fallback 函数会调用. 如果两个函数都没有,这个合约就没法通过常规的转账交易接收以太(会抛出异常). 更糟的是,receive 函数可能只有 2300 gas 可以使用(如,当使用 send 或 transfer 时), 除了基础的日志输出之外,进行其他操作的余地很小。下面的操作消耗会操作 2300 gas : 写入存储 创建合约 调用消耗大量 gas 的外部函数 发送以太币
合约可以最多有一个回退函数。函数声明为: fallback () external [payable] 或 fallback (bytes calldata _input) external [payable] returns (bytes memory _output) 没有 function 关键字。 必须是 external 可见性,它可以是 virtual 的,可以被重载也可以有 修改器modifier 。 如果在一个对合约调用中,没有其他函数与给定的函数标识符匹配fallback会被调用. 或者在没有 receive 函数 时,而没有提供附加数据对合约调用,那么fallback 函数会被执行。 fallback 函数始终会接收数据,但为了同时接收以太时,必须标记为 payable 。 如果使用了带参数的版本,_input 将包含发送到合约的完整数据(等于 msg.data ),并且通过 _output 返回数据。 返回数据不是 ABI 编码过的数据,相反,它返回不经过修改的数据。 更糟的是,如果回退函数在接收以太时调用,可能只有 2300 gas 可以使用,参考 receive接收函数 与任何其他函数一样,只要有足够的 gas 传递给它,回退函数就可以执行复杂的操作。
一个没有定义 fallback 函数或 receive 函数的合约,直接接收以太币(没有函数调用,即使用 send 或 transfer)会抛出一个异常, 并返还以太币
不定义fallback或receiver回退函数,call仍然可以执行 send或transfer无法执行
通过在账户地址指定msg.value实现向合约账户转账
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.0; // 向合约账户转账 contract terans{ // 向合约账户转账 ev event TransEvent(address,uint); //trigger recevier function //纯转账调用receiver回退函数,例如对每个空empty calldata的调用 function transderToContract() payable public { payable(address(this)).transfer(msg.value); } // 获取合约账户余额 function getBalanceOfContract() public view returns (uint256) { return address(this).balance; } //trigger recevier function //纯转账调用receiver回退函数,例如对每个空empty calldata的调用 //对函数方法的调用 出发receiver回退函数 function CallTransTest()payable public{ (bool success,) = address(this).call(abi.encodeWithSignature("transderToContract()")); //emit TransEvent(address(this),2); } //trigger fallback function // 除了纯转账外,所有的调用都会调用这个函数. // (因为除了 receive 函数外,没有其他的函数). // 任何对合约非空calldata 调用会执行回退函数(即使是调用函数附加以太). function CallNoexistTest()payable public{ (bool success,) = address(this).call(abi.encodeWithSignature("noFunction()")); //emit TransEvent(address(this),2); } fallback() external payable { emit TransEvent(address(this),1); } receive() external payable { emit TransEvent(address(this),2); } }