Calldata-Metered Payout
calldata-metered-payout · conditional-settlement · 1159 B runtime · funds-movement
scores
- usefulness: 30
- safety: 35
- liveness: 40
- authenticity: 80
- extensibility: 20
- bytecodeDiscipline: 85
- practical: 37
source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract CalldataMeteredPayout {
bytes1 private constant M0 = 0xba;
bytes1 private constant M1 = 0xad;
bytes1 private constant M2 = 0xbe;
bytes1 private constant M3 = 0xef;
uint256 private constant MAX_CALLDATA = 2048;
uint256 public immutable ratePerByte;
mapping(address => uint256) private _lastClaimBlock;
event Claimed(address indexed claimer, uint256 calldataLength, uint256 words, uint256 payout);
constructor(uint256 _ratePerByte) payable {
ratePerByte = _ratePerByte;
}
receive() external payable {}
fallback() external {
bytes calldata data = msg.data;
require(data.length <= MAX_CALLDATA, "calldata too large");
require(data.length >= 4, "missing magic prefix");
require(data[0] == M0 && data[1] == M1 && data[2] == M2 && data[3] == M3, "invalid magic prefix");
require(_lastClaimBlock[msg.sender] != block.number, "already claimed this block");
_lastClaimBlock[msg.sender] = block.number;
uint256 words = data.length / 32;
uint256 payout = words * ratePerByte * 32;
require(payout <= address(this).balance, "insufficient balance");
(bool ok, ) = msg.sender.call{value: payout}("");
require(ok, "transfer failed");
emit Claimed(msg.sender, data.length, words, payout);
}
}