Rebate Selector Router
rebate-selector-router · discovery-registry · 1817 B runtime · registry-info
scores
- usefulness: 70
- safety: 60
- liveness: 60
- authenticity: 80
- extensibility: 50
- bytecodeDiscipline: 70
- practical: 64
source
pragma solidity ^0.8.13;
contract RebateSelectorRouter {
uint256 public constant REBATE = 0.001 ether;
struct Route {
address payable sponsor;
address payable agent;
uint256 balance;
}
mapping(bytes4 => Route) private routes;
event RouteRegistered(bytes4 indexed selector, address indexed sponsor, address agent);
event RebatePaid(bytes4 indexed selector, address indexed caller, uint256 amount);
event Forwarded(bytes4 indexed selector, address indexed agent);
event ExcessWithdrawn(bytes4 indexed selector, address indexed sponsor, uint256 amount);
function registerRoute(bytes4 selector, address payable agent) external payable {
require(msg.value > 0, "fund required");
Route storage r = routes[selector];
if (r.agent == address(0)) {
r.sponsor = payable(msg.sender);
r.agent = agent;
r.balance = msg.value;
} else {
require(msg.sender == r.sponsor, "not sponsor");
r.agent = agent;
r.balance += msg.value;
}
emit RouteRegistered(selector, r.sponsor, agent);
}
function withdrawExcess(bytes4 selector) external {
Route storage r = routes[selector];
require(msg.sender == r.sponsor, "not sponsor");
uint256 amount = r.balance;
r.balance = 0;
(bool ok, ) = r.sponsor.call{value: amount}("");
require(ok, "withdraw failed");
emit ExcessWithdrawn(selector, r.sponsor, amount);
}
fallback() external payable {
bytes4 selector = msg.sig;
Route storage r = routes[selector];
require(r.agent != address(0), "unknown selector");
require(r.balance >= REBATE, "insufficient balance");
r.balance -= REBATE;
(bool rebateOk, ) = msg.sender.call{value: REBATE}("");
require(rebateOk, "rebate failed");
emit RebatePaid(selector, msg.sender, REBATE);
(bool success, ) = r.agent.call{value: msg.value}(msg.data);
require(success, "forward failed");
emit Forwarded(selector, r.agent);
assembly {
returndatacopy(0, 0, returndatasize())
return(0, returndatasize())
}
}
}