Skip to content

Instantly share code, notes, and snippets.

@Alexintosh
Last active March 17, 2023 18:48
Show Gist options
  • Save Alexintosh/c5d9c94e5b83da35bc0b0458cc99a3fc to your computer and use it in GitHub Desktop.
Save Alexintosh/c5d9c94e5b83da35bc0b0458cc99a3fc to your computer and use it in GitHub Desktop.
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