Transfer() and send() have been recommended as a security best-practice to prevent reentrancy attacks because they only forward 2300 gas. That being said, gas repricing of opcodes may break deployed contracts.
Proof of Concept
references
---ChainSecurity - Ethereum Istanbul Hardfork: The Security Perspective
---Steve Marx - Stop Using Solidity’s transfer() Now
---EIP 1884
---Consensys - https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/
Ex:
contract Vulnerable {
function withdraw(uint256 amount) external {
// This forwards 2300 gas, which may not be enough if the recipient
// is a contract and gas costs change.
msg.sender.transfer(amount);
}
}
contract Fixed {
function withdraw(uint256 amount) external {
// This forwards all available gas. Be sure to check the return value!
(bool success, ) = msg.sender.call.value(amount)("");
require(success, "Transfer failed.");
}
}
Tools Used
VIM
Recommended Mitigation Steps
Use call() instead, without hardcoded gas limits along with checks-effects-interactions pattern or reentrancy guards for reentrancy protection.
Lines of code
https://github.com/code-423n4/2022-06-putty/blob/main/contracts/test/mocks/MockWeth.sol#L22-L25
Vulnerability details
Impact
Transfer() and send() have been recommended as a security best-practice to prevent reentrancy attacks because they only forward 2300 gas. That being said, gas repricing of opcodes may break deployed contracts.
Proof of Concept
references ---ChainSecurity - Ethereum Istanbul Hardfork: The Security Perspective ---Steve Marx - Stop Using Solidity’s transfer() Now ---EIP 1884 ---Consensys - https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/ Ex: contract Vulnerable { function withdraw(uint256 amount) external { // This forwards 2300 gas, which may not be enough if the recipient // is a contract and gas costs change. msg.sender.transfer(amount); } }
contract Fixed { function withdraw(uint256 amount) external { // This forwards all available gas. Be sure to check the return value! (bool success, ) = msg.sender.call.value(amount)(""); require(success, "Transfer failed."); } }
Tools Used
VIM
Recommended Mitigation Steps
Use call() instead, without hardcoded gas limits along with checks-effects-interactions pattern or reentrancy guards for reentrancy protection.