英文:
Why am I unable to send ether to other contract with 'send' or 'transfer' function?
问题
为什么 `send()` 和 `transfer()` 不起作用?
我刚学会了Solidity,对发送以太币的方法很感兴趣。
我在Solidity中编写了两个智能合约,并在Remix IDE中部署了它们(环境为Remix VM(Merge))。我尝试以三种不同的方式从发送方合约向接收方合约发送1个以太币,分别是 `send()`、`transfer()` 和 `call()`。
我能够通过 `call()` 方法发送以太币,但无法使用 `send()` 和 `transfer()` 函数发送。
以下是代码。
```solidity
pragma solidity ^0.8.0;
contract Receiver {
// ...(代码省略)
}
contract Sender {
// ...(代码省略)
}
发送方合约有三个函数,分别是 "sendWithSend"、"sendWithTransfer" 和 "sendWithCall"。
我尝试使用每个函数向接收方合约发送1个以太币,我期望它们都能成功,使接收方合约拥有3个以太币。但实际上只有1个以太币。
call()
方法起作用,但 send()
和 transfer()
失败。
我尝试了很多次,但 send()
和 transfer()
从未起作用。
以下是错误日志:
send()
错误:
transfer()
错误:
call()
方法成功日志:
我非常感谢您的帮助。
<details>
<summary>英文:</summary>
Why `send()` and `transfer()` doesn't work?
I just learned solidity and I'm curious about the methods of sending ether.
I wrote two smart contract in solidity and deployed them with Remix IDE(Environment is Remix VM(Merge)). I tried to send 1 ether from Sender contract to Receiver contract in three different ways, `send()`, `transfer()`, `call()`.
I was able to send ether trough `call()`, but I was unable to send ether with `send()` and `transfer()` function.
Here is the code.
pragma solidity ^0.8.0;
contract Receiver {
address receiver;
uint public prize;
address public owner;
constructor() payable {
receiver = msg.sender;
owner = msg.sender;
prize = 0.001 ether;
}
receive() external payable {
require(msg.value >= prize || msg.sender == owner);
payable(receiver).transfer(msg.value);
receiver = msg.sender;
prize = msg.value;
}
}
contract Sender {
constructor() payable{
}
function sendWithSend(address payable _to) public payable{
//send ether with send
//failed
bool success = _to.send(msg.value);
require(success, "failed");
}
function sendWithTransfer(address payable _to) public payable{
//send ether with transfer
//failed
_to.transfer(msg.value);
}
function sendWithCall(address payable _to) public payable{
//send ether with call
//success
(bool sent, ) = _to.call{value: msg.value}("");
require(sent, "Failled" );
}
}
Sender contract has three functions, "sendWithSend", "sendWithTransfer" and "sendWithCall".
I tried to sent 1 ether to Receiver contract with each function and I expected all worked so Receiver contract would have 3 ether. But it got only 1 ether.
`call()` worked but `send()` and `transfer()` failed.
I tried many times but `send()` and `transfer()` never works.
here is the error log
`send()` error
[send error log 1](https://i.stack.imgur.com/UVw9j.png)
[send error log 2](https://i.stack.imgur.com/umzAV.png)
`transfer()` error
[transfer error log 1](https://i.stack.imgur.com/kKM4c.png)
[transfer error log 2](https://i.stack.imgur.com/Leaw2.png)
and here is `call()` method success log
[call success log](https://i.stack.imgur.com/TqBho.png)
I would really appreciate your help.
</details>
# 答案1
**得分**: 0
send() 和 transfer() 的燃气限制为 21000,而 call() 没有默认的燃气限制。
对于 send() 和 transfer() 函数,当接收到资金时,receive() 函数将执行额外的代码,这将达到燃气限制。因此,交易将被回滚。
如果你创建一个空的 receive 函数,那么这应该可以工作,因为不会达到燃气限制。
这就是为什么最佳实践是始终使用 call() 函数,如果你可能要与智能合同交互的话。
<details>
<summary>英文:</summary>
send() and transfer() have a gas limit of 21000 while call() does not have default gas limit.
For the send() and transfer() function, when the funds are received, the receive() function will execute additional code which will reach the gas limit. Therefor the transaction will be reverted.
If you make an empty receive function, this should work as the gas limit will not be reached.
This is why the best practice is to always use the call() function if you may interact with a smart contract.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论