Within the final submit Pressure Ship ETH – 1, we understood about selfdestruct
and the way it’s used to forcefully ship ETH to any contract.
Now let’s take an instance to know what is the vulnerability on this. Think about the next contract:
contract Crowdfund {
// this contract solely accepts a specific amount of funds
// if somebody tries to ship an quantity that exceeds contract stability greater than the restrict, tnx fails
// funds are transfered to an handle solely when contract stability equals fund restrict
uint fundLimit = 3 ether;
bool contractOpen = true;
operate donate() exterior payable { // for others to donate eth to this contract
require(contractOpen, "Contract has stopped recieving funds");
require(handle(this).stability <= fundLimit, "Cannot ship specified quantity");
// word: we can not do handle(this).stability + msg.worth, as a result of handle(this).stability already takes msg.worth
}
operate getBalance() exterior view returns(uint) { // to get present stability of this contract
return handle(this).stability;
}
operate sendFunds() exterior { // to ship all collected funds
require(contractOpen, "Contract has stopped recieving funds");
require(handle(this).stability == fundLimit, "Fund restrict not reached but");
contractOpen = false; // contract closed
payable(handle(0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB)).switch(handle(this).stability);
}
}
Now contemplate the next state of affairs:
- Contract stability has reached 3 ether, however some hacker force-sends additional ETH to CrowdFund contract handle.
- Now contract stability > fundLimit, therefore
require(handle(this).stability == fundLimit, "Fund restrict not reached but");
from thesendFunds()
operate will fail and never let anybody ship the collected funds to required receiver.
Hope you bought an concept about what precisely the vulnerability is.
Let’s have a look at the attacker contract:
contract Attacker{
fallback() exterior payable {
}
operate assault(handle _crowdFund) exterior {
selfdestruct(payable(_crowdFund));
}
}
Until now we understood what precisely this vulnerability is and the way hackers can benefit from it. Let’s now see tips on how to keep away from such hacks.
- one answer is to vary
require(handle(this).stability == fundLimit, "Fund restrict not reached but");
to
require(handle(this).stability >= fundLimit, "Fund restrict not reached but");
in sendFunds()
operate of Crowdfund
contract.
However what if that is an vital situation for some utility?
- higher answer is to keep away from utilizing
handle(this)
to trace funds
Let’s have a look at the next contract to know this higher:
contract CrowdFund_safe{
uint fundLimit = 3 ether;
bool contractOpen = true;
uint stability = 0;
operate donate() exterior payable { // for others to donate eth to this contract
require(contractOpen, "Contract has stopped recieving funds");
require(stability + msg.worth <= fundLimit, "Cannot ship specified quantity");
stability += msg.worth;
}
operate getBalance() exterior view returns(uint) { // to get present stability of this contract
return handle(this).stability;
}
operate sendFunds() exterior { // to ship all collected funds
require(contractOpen, "Contract has stopped recieving funds");
require(stability == fundLimit, "Fund restrict not reached but");
contractOpen = false; // contract closed
payable(handle(0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB)).switch(stability);
}
}
Now even when hacker force-sends ETH to this contract, it will not change the stability
state variable, therefore this would possibly not have an effect on any situations within the contract.
Therefore the contract is protected from such assaults.