Gas-burn micro-payment
gas-burn-micro-payment · conditional-settlement · 1249 B runtime · funds-movement
scores
- usefulness: 55
- safety: 65
- liveness: 45
- authenticity: 90
- extensibility: 55
- bytecodeDiscipline: 75
- practical: 58
source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract GasBurnMicroPayment {
uint256 public constant MAX_GAS_TARGET = 50_000;
uint256 private constant MIN_RESERVE_GAS = 5_000;
address public owner;
uint256 public threshold;
bool private locked;
event ThresholdSet(uint256 newThreshold);
event Claimed(address indexed claimant, uint256 amount);
constructor(uint256 initialThreshold) {
require(initialThreshold > 0 && initialThreshold <= MAX_GAS_TARGET, "bad initial threshold");
owner = msg.sender;
threshold = initialThreshold;
}
modifier onlyOwner() {
require(msg.sender == owner, "unauthorized");
_;
}
modifier nonReentrant() {
require(!locked, "reentrant");
locked = true;
_;
locked = false;
}
receive() external payable {}
function setThreshold(uint256 newThreshold) external onlyOwner {
require(newThreshold > 0 && newThreshold <= MAX_GAS_TARGET, "bad threshold");
threshold = newThreshold;
emit ThresholdSet(newThreshold);
}
function claim() external nonReentrant {
require(address(this).balance > 0, "no balance");
uint256 startGas = gasleft();
require(startGas >= threshold + MIN_RESERVE_GAS, "insufficient gas");
uint256 targetGas = startGas - threshold;
assembly {
for { } gt(gas(), targetGas) { } {
mstore(0, gas())
}
}
uint256 gasUsed = startGas - gasleft();
require(gasUsed >= threshold, "burn below threshold");
require(gasleft() > MIN_RESERVE_GAS, "reserve too low");
uint256 amount = address(this).balance;
(bool ok, ) = msg.sender.call{value: amount}("");
require(ok, "transfer failed");
emit Claimed(msg.sender, amount);
}
}