Last active
March 17, 2023 18:48
-
-
Save Alexintosh/c5d9c94e5b83da35bc0b0458cc99a3fc to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity 0.8.13; | |
import "hardhat/console.sol"; | |
contract AtomicityGuard { | |
// address => block => status | |
uint256 private constant _ENTERED = 1; | |
mapping(address => mapping( uint256 => uint256)) ledger; | |
modifier nonAtomic() { | |
_nonAtomicBefore(); | |
_; | |
} | |
function _nonAtomicBefore() private { | |
// On the first call to nonReentrant, _status will be _NOT_ENTERED | |
require(ledger[msg.sender][block.number] != _ENTERED, "AtomicityGuard: same block"); | |
ledger[msg.sender][block.number] = _ENTERED; | |
} | |
} | |
contract BufferGuard is AtomicityGuard { | |
// address => block => status | |
uint256 private blockBuffer; | |
uint256 private constant _ENTERED = 1; | |
mapping(address => uint256) lastSeen; | |
constructor(uint256 _buff) { | |
blockBuffer = _buff; | |
} | |
modifier buffered() { | |
console.log(lastSeen[msg.sender]); | |
console.log(block.number); | |
_buffered(); | |
_; | |
} | |
function _buffered() private nonAtomic { | |
// On the first call to nonReentrant, _status will be _NOT_ENTERED | |
if(lastSeen[msg.sender] > 0) { | |
require(block.number > lastSeen[msg.sender] + blockBuffer, "BufferGuard: not buffered"); | |
} | |
lastSeen[msg.sender] = block.number; | |
} | |
} | |
contract ImplementorBuffered is BufferGuard { | |
constructor() BufferGuard(10) {} | |
function deposit() external buffered { | |
} | |
function withdraw() external buffered { | |
} | |
} | |
contract Implementor is AtomicityGuard { | |
function deposit() external nonAtomic { | |
} | |
function withdraw() external nonAtomic { | |
} | |
} | |
interface IImplementor { | |
function deposit() external; | |
function withdraw() external; | |
} | |
contract Exploiter { | |
IImplementor c; | |
constructor (address _i) { | |
c = IImplementor(_i); | |
} | |
function atomic() external { | |
c.deposit(); | |
c.withdraw(); | |
} | |
function nonatomicDeposit() external { | |
c.deposit(); | |
} | |
function nonatomicWithdraw() external { | |
c.withdraw(); | |
} | |
} | |
contract Exploiter2 { | |
constructor (address _i) { | |
IImplementor(_i).deposit(); | |
IImplementor(_i).withdraw(); | |
selfdestruct(payable(msg.sender)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment