An Interest In:
Web News this Week
- April 26, 2024
- April 25, 2024
- April 24, 2024
- April 23, 2024
- April 22, 2024
- April 21, 2024
- April 20, 2024
Prevent External Contracts
Almost every vulnerability you see in solidity smart contracts are caused by hackers developing some attacker contract and this attacker contract then harming the vulnerable contract.
By the way, I have made a series on smart contract vulnerabilities if you find it interesting (link)
But what if there is a way by which we can know if function caller is a contract or a normal wallet address?
Then we can stop any external contract from interacting with our contract, hence saving our contract from being hacked.
Let's see how this can be achieved:
- consider a contract vulnerable to re-entrancy (check my re-entracy blog)
- in this case, hacker will take advantage of late balance update in state mapping, and will keep on re-entering contract using his attacker contract until all funds are drained.
- but not if we stop external contracts to call
MyContract
functions.
// SPDX-License-Identifier: GPL-3.0pragma solidity 0.8.1;contract MyContract { // this contract is vulnerable to re-entracy attack mapping (address => uint) balances; modifier noContract { // this won't allow external contracts to interact with this contract require(tx.origin == msg.sender, "No contracts allowed"); _; } function deposit() external payable noContract { // using noContract balances[msg.sender] += msg.value; } function withdraw() external payable noContract { // using noContract uint amount = balances[msg.sender]; require(amount > 0, "Nothing to withdraw"); (bool sent, ) = msg.sender.call{value: amount}(""); require(sent, "Send operation failed"); balances[msg.sender] = 0; } function getBalance() external view returns(uint balance) { balance = address(this).balance; }}
We are stopping external smart contracts using noContract
modifier. It verifies if function caller(msg.sender
) is same as transaction initiator(tx.origin
).
Wanna know more about tx.origin
? Visit here
Now when some Attacker contract will try to steal funds from MyContract, transaction will fail.
Attacker contract:
// SPDX-License-Identifier: GPL-3.0pragma solidity 0.8.1;interface IMyContract{ function deposit() external payable; function withdraw() external payable;}contract Attacker { IMyContract myContract; constructor(address _myContract) payable { myContract = IMyContract(_myContract); } fallback() external payable { if (address(myContract).balance > 0) { myContract.withdraw(); } } function attack() external payable { myContract.deposit{value: 1 ether}(); myContract.withdraw(); } function getBalance() external view returns(uint balance) { balance = address(this).balance; }}
Original Link: https://dev.to/rushanksavant/prevent-contract-to-call-1bfk
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To