To transfer Ethers to another contract, developers can use send()
, transfer()
, and call()
.
IMHO, this design is problematic.
-
send()
andcall()
do not throw exceptions, and developers have to manually check their return values to see whether the call is successful. However, it is not enforced by the compiler, so developers can write error-prone code. -
transfer()
throws exceptions and forces a revert. It is safe, but it seems there is no way for developers to explicitly ignore an exception. Thetry
/catch
syntax does not work fortransfer()
.
Explicitness is better than implicitness. Although a simple send()
can achieve Ether transfer and ignoring whether it succeeds, I suggest an explicit syntax that enforces safety, and at the same time developers can explicitly ignore an exception. For example:
contract Test {
function foo(address payable receiver) public {
try receiver.transfer(1 ether) {
// do something if it succeeds
} catch (bytes memory lowLevelData) {
// can ignore when it fails
}
}
}
Or more concisely, a syntax from Swift: (note that in Swift try!
has a different meaning)
contract Test {
function foo(address payable receiver) public {
try! receiver.transfer(1 ether);
// will continue to run regardless of whether the transfer succeeds
}
}