File 1 of 1: RevShareContract.sol
pragma solidity ^0.8.0;
contract RevShareContract {
address public owner;
address public incentivesAddress;
uint256 public currentRound = 0;
struct Round {
uint256 revenueForBB;
uint256 revenueForBettingVolume;
uint256 revenueForReferrals;
uint256 totalBBTokens;
uint256 totalBettingVolume;
uint256 totalReferrals;
uint256 startTime;
bool isSnapshotUploaded;
mapping(address => uint256) snapshotBBBalances;
mapping(address => uint256) snapshotBettingVolume;
mapping(address => uint256) snapshotReferrals;
}
mapping(uint256 => Round) public rounds;
mapping(uint256 => mapping(address => bool)) hasClaimedBB;
mapping(uint256 => mapping(address => bool)) hasClaimedBettingVolume;
mapping(uint256 => mapping(address => bool)) hasClaimedReferral;
event EthClaim(address indexed claimer, uint256 amount, uint256 round);
event AdminWithdraw(uint256 amount, uint256 round);
modifier onlyOwner() {
require(msg.sender == owner, "Caller is not the owner");
_;
}
bool private locked;
modifier noReentrant() {
require(!locked, "Reentrant call detected");
locked = true;
_;
locked = false;
}
constructor(address _incentivesAddress) {
owner = msg.sender;
incentivesAddress = _incentivesAddress;
}
function depositRevenue(uint256 bbRevenue, uint256 bettingVolumeRevenue, uint256 referralsRevenue, uint256 incentivesRevenue) external payable onlyOwner {
require(msg.value == bbRevenue + bettingVolumeRevenue + referralsRevenue + incentivesRevenue, "Mismatch in sent value and declared revenue distribution.");
currentRound += 1;
rounds[currentRound].startTime = block.timestamp;
rounds[currentRound].revenueForBB = bbRevenue;
rounds[currentRound].revenueForBettingVolume = bettingVolumeRevenue;
rounds[currentRound].revenueForReferrals = referralsRevenue;
payable(incentivesAddress).transfer(incentivesRevenue);
}
function uploadBBBalances(address[] calldata bbHolders, uint256[] calldata bbBalances) external onlyOwner {
require(currentRound > 0, "Deposit revenue first");
Round storage r = rounds[currentRound];
require(!r.isSnapshotUploaded, "Snapshot already uploaded for this round");
for (uint256 i = 0; i < bbHolders.length; i++) {
r.snapshotBBBalances[bbHolders[i]] = bbBalances[i];
r.totalBBTokens += bbBalances[i];
}
}
function uploadBettingVolumes(address[] calldata betters, uint256[] calldata bettingVolumes) external onlyOwner {
require(currentRound > 0, "Deposit revenue first");
Round storage r = rounds[currentRound];
require(!r.isSnapshotUploaded, "Snapshot already uploaded for this round");
for (uint256 i = 0; i < betters.length; i++) {
r.snapshotBettingVolume[betters[i]] = bettingVolumes[i];
r.totalBettingVolume += bettingVolumes[i];
}
}
function uploadReferrals(address[] calldata referrers, uint256[] calldata referralAmounts) external onlyOwner {
require(currentRound > 0, "Deposit revenue first");
Round storage r = rounds[currentRound];
require(!r.isSnapshotUploaded, "Snapshot already uploaded for this round");
for (uint256 i = 0; i < referrers.length; i++) {
r.snapshotReferrals[referrers[i]] = referralAmounts[i];
r.totalReferrals += referralAmounts[i];
}
}
function lockSnapshot() external onlyOwner {
require(currentRound > 0, "Deposit revenue first");
Round storage r = rounds[currentRound];
require(!r.isSnapshotUploaded, "Snapshot already uploaded for this round");
r.isSnapshotUploaded = true;
}
function claimBB(uint256 roundNumber) external noReentrant {
require(roundNumber > 0 && roundNumber <= currentRound, "Invalid round number");
Round storage r = rounds[roundNumber];
require(r.isSnapshotUploaded, "Snapshot not uploaded for this round");
require(!hasClaimedBB[roundNumber][msg.sender], "You have already claimed BB for this round");
require(r.snapshotBBBalances[msg.sender] > 0, "No BB balance to claim");
uint256 claimAmount = (r.revenueForBB * r.snapshotBBBalances[msg.sender]) / r.totalBBTokens;
hasClaimedBB[roundNumber][msg.sender] = true;
(bool success,) = msg.sender.call{value: claimAmount}("");
require(success, "Claim BB transfer failed");
emit EthClaim(msg.sender, claimAmount, roundNumber);
}
function claimBettingVolume(uint256 roundNumber) external noReentrant {
require(roundNumber > 0 && roundNumber <= currentRound, "Invalid round number");
Round storage r = rounds[roundNumber];
require(r.isSnapshotUploaded, "Snapshot not uploaded for this round");
require(!hasClaimedBettingVolume[roundNumber][msg.sender], "You have already claimed Betting Volume for this round");
require(r.snapshotBettingVolume[msg.sender] > 0, "No Betting Volume to claim");
uint256 claimAmount = (r.revenueForBettingVolume * r.snapshotBettingVolume[msg.sender]) / r.totalBettingVolume;
hasClaimedBettingVolume[roundNumber][msg.sender] = true;
(bool success,) = msg.sender.call{value: claimAmount}("");
require(success, "Claim Betting Volume transfer failed");
emit EthClaim(msg.sender, claimAmount, roundNumber);
}
function claimReferral(uint256 roundNumber) external noReentrant {
require(roundNumber > 0 && roundNumber <= currentRound, "Invalid round number");
Round storage r = rounds[roundNumber];
require(r.isSnapshotUploaded, "Snapshot not uploaded for this round");
require(!hasClaimedReferral[roundNumber][msg.sender], "You have already claimed Referrals for this round");
require(r.snapshotReferrals[msg.sender] > 0, "No Referrals to claim");
uint256 claimAmount = (r.revenueForReferrals * r.snapshotReferrals[msg.sender]) / r.totalReferrals;
hasClaimedReferral[roundNumber][msg.sender] = true;
(bool success,) = msg.sender.call{value: claimAmount}("");
require(success, "Claim Referral transfer failed");
emit EthClaim(msg.sender, claimAmount, roundNumber);
}
function claimableBB(address userAddress, uint256 roundNumber) external view returns (uint256) {
require(roundNumber > 0 && roundNumber <= currentRound, "Invalid round number");
Round storage r = rounds[roundNumber];
require(r.isSnapshotUploaded, "Snapshot not uploaded for this round");
if (hasClaimedBB[roundNumber][userAddress]) {
return 0;
}
if (r.snapshotBBBalances[userAddress] > 0) {
return (r.revenueForBB * r.snapshotBBBalances[userAddress]) / r.totalBBTokens;
}
return 0;
}
function claimableBettingVolume(address userAddress, uint256 roundNumber) external view returns (uint256) {
require(roundNumber > 0 && roundNumber <= currentRound, "Invalid round number");
Round storage r = rounds[roundNumber];
require(r.isSnapshotUploaded, "Snapshot not uploaded for this round");
if (hasClaimedBettingVolume[roundNumber][userAddress]) {
return 0;
}
if (r.snapshotBettingVolume[userAddress] > 0) {
return (r.revenueForBettingVolume * r.snapshotBettingVolume[userAddress]) / r.totalBettingVolume;
}
return 0;
}
function claimableReferral(address userAddress, uint256 roundNumber) external view returns (uint256) {
require(roundNumber > 0 && roundNumber <= currentRound, "Invalid round number");
Round storage r = rounds[roundNumber];
require(r.isSnapshotUploaded, "Snapshot not uploaded for this round");
if (hasClaimedReferral[roundNumber][userAddress]) {
return 0;
}
if (r.snapshotReferrals[userAddress] > 0) {
return (r.revenueForReferrals * r.snapshotReferrals[userAddress]) / r.totalReferrals;
}
return 0;
}
function setIncentivesAddress(address _newIncentivesAddress) external onlyOwner {
incentivesAddress = _newIncentivesAddress;
}
function withdrawUnclaimed(uint256 roundNumber) public onlyOwner {
require(roundNumber > 0 && roundNumber <= currentRound, "Invalid round number");
Round storage r = rounds[roundNumber];
require(block.timestamp >= r.startTime + 60 days, "Cannot withdraw before 60 days have passed since the start of the specified round");
uint256 unclaimedBB = r.revenueForBB;
uint256 unclaimedBetting = r.revenueForBettingVolume;
uint256 unclaimedReferrals = r.revenueForReferrals;
r.revenueForBB = 0;
r.revenueForBettingVolume = 0;
r.revenueForReferrals = 0;
(bool success,) = msg.sender.call{value: unclaimedBB + unclaimedBetting + unclaimedReferrals}("");
require(success, "Withdraw failed");
emit AdminWithdraw(unclaimedBB + unclaimedBetting + unclaimedReferrals, roundNumber);
}
receive() external payable {
revert("Send ETH using depositRevenue function");
}
}
{
"compilationTarget": {
"RevShareContract.sol": "RevShareContract"
},
"evmVersion": "shanghai",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}