-
Notifications
You must be signed in to change notification settings - Fork 276
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handling Ether in a smart contract. #67
Comments
This is kinda more a list of multiple different vulnerabilities and heuristics, one or two of which are kinda already included, so not sure how this fits in. I do like "Using msg.value in a loop" though, perhaps that would be worth making into it's own listed vulnerability? |
The main idea behind listing like this is this includes all the vulnerabilities regarding handling ether and msg.value in a single document. Some of these are already included but i wanted to provide a single document mentioning the assumptions, how they can be exploited and their fixes and I thought this would make reading about similar vulnerabilities more easier and intuitive. I can see how this would not fit in the existing repo as this feels more like a blog post. Yeah, I will make |
If force feeding doesn't mention selfdestruct usage then we should probably add it under that vuln imo |
Author of the force-feeding issue here, the reason why I didn't include |
It is depreciated in 0.8.18 which is relatively new and a lot of contracts use version >=0.8.0 to 0.8.18. Also, If EIP-4758 gets implemented and |
Agree with @0xSandyy here, as long as it is possible to execute an attack it should be listed. Even if selfdestruct gets unsupported entirely on some networks it's worth still including for the few that will likely still support it |
Checklist
Type of Issue
Description
Handling Ether
Ether is the native cryptocurrency of the Ethereum network. It serves as the fuel that powers the execution of smart contracts, enables transactions, and facilitates interactions within the Ethereum ecosystem. The following things should be considered while handling ether:
Use of Call / Send / Transfer while transferring tokens
The
transfer()
andsend()
functions forward a fixed amount of2300 gas
. Historically, it has often been recommended to use these functions for value transfers to guard against reentrancy attacks. However, the gas cost of EVM instructions may change significantly during hard forks which may break already deployed contract systems that make fixed assumptions about gas costs. For example. EIP 1884 broke several existing smart contracts due to a cost increase of the SLOAD instruction. Additionally, using higher than 2300 gas might be mandatory for some multisig wallets. Thus, usingcall()
and checking forsuccess
is recommended but transferring ether to any untrusted address may cause gas-griefing due to unbounded return data issue.Accounting for selfdestruct to forcibly send ether
The first assumption that is made with handling ether in a smart contract is ether can only be sent to a contract if the contract contains either a
receive()
or afallback()
function and these functions can be modified to track the incoming balances but this is not the only way.selfdestruct
sends all remaining Ether stored in the contract to a designated address before destroying a contract. Example. Thus an attacker can useselfdestruct
to send ether to a contract with noreceive()
orfallback()
function to mess up the internal accounting if contract strictly relies onaddress(this).balance
.Locked Ether
The locked ether vulnerability can occur when a smart contract accepts ether but does not provide a way for users to withdraw it or having no way to recover excess ether that might be locked to due faulty business logic or some users accidentally sending ether to the contract with
receive()
/fallback()
function.Implement a withdraw or recover function to recover excess ether from the contract.
Pull vs Push pattern for sending ether
While transferring ether in a
loop
, It must be considered that if any one of the iterations of sending ether to a recipient fails, the whole function reverts. This call to transfer tokens can fail due to various reasons likegas-griefing
, recipient not implementingfallback()
, malicious recipient force revertingfallback()
, etc.If there is no way to withdraw funds from the contract other than looping through a pre-configured list of recipients, this might cause a serious problem. Therefore, a push pattern should be used. It can be implemented by adding a function from which valid recipients can withdraw funds themselves.
Using
msg.value
in a loopThe particularity with
msg.value
is that msg.value is set on every contract call and not on the transaction level. Thus, if the function with loop is transferringmsg.value
on every iteration, all themsg.value
sent to the function is transferred in the first iteration and other iteration will proceed withmsg.value = 0
which may cause unexpected consequences.Also, if a function has a check like
msg.value > 0.1e18
, that function can be called multiple times in a same transaction asmsg.value
value is not subtracted unless it's transferred out of the contract.Sources
The text was updated successfully, but these errors were encountered: