Contract - Code
Optimism Mainnet (10): https://optimistic.etherscan.io/address/0xBBBcad6EdBCBE647FBe273fb588cb5e8E1B385da#code BNB SmartChain (56): https://bscscan.com/address/0xBBBcad6EdBCBE647FBe273fb588cb5e8E1B385da#code Polygon Mainnet (137): https://polygonscan.com/address/0xBBBcad6EdBCBE647FBe273fb588cb5e8E1B385da#code
Arbitrum One (42161): https://arbiscan.io/address/0xBBBcad6EdBCBE647FBe273fb588cb5e8E1B385da#code ====== Revamp Contract =====
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
/**
* @title Revamp
* @notice Decentralized protocol for token listing, revamp (burn), referral rewards, and native value redistribution.
* Includes a global per-wallet native contribution cap (owner adjustable) and initial participant migration logic.
*/
contract Revamp is ReentrancyGuard, Ownable {
using SafeERC20 for IERC20;
// ββββββββββββββ Constants ββββββββββββββ
uint256 public constant PRECISION = 1e18;
// ββββββββββββββ Structs ββββββββββββββ
struct UserInfo {
uint256 totalContributed; // Native sent by user (principal)
uint256 rewardDebt; // Used for reward calculations
uint256 claimedSoFar; // Total claimed rewards
}
struct TokenInfo {
uint256 rate; // Fixed revamp rate (token per native)
address lister; // Who listed this token
string logoUrl;
uint8 decimals;
string name;
string symbol;
}
struct TokenData {
address token;
uint256 rate;
address lister;
string logoUrl;
uint8 decimals;
string name;
string symbol;
}
// ββββββββββββββ State Variables ββββββββββββββ
// Contribution cap
uint256 public maxContributionPerWallet;
// Referral system
mapping(address => address) public referrerOf;
address public genesisAddress;
uint256 public referralFeePercent;
// Listed tokens and info
mapping(address => TokenInfo) public tokenInfos;
address[] private listedTokens;
// Fee parameters
uint256 public listingFee;
uint256 public claimFee;
uint256 public delistFee;
address public feeRecipient;
uint256 public totalListingFees;
// Revenue splits
uint256 public nativeFeePercent;
address public nativeFeeRecipient;
uint256 public shareholdingFeePercent;
address public shareholdingFeeRecipient;
uint256 public fastLineFeePercent;
address public fastLineFeeRecipient;
// βοΈ NEW: Cumulative sum of all Fast Line fees forwarded
uint256 public totalFastLineFees;
// Reward/accounting variables
uint256 public totalNativeContributed;
uint256 public accRewardPerShare;
mapping(address => UserInfo) public users;
address[] public topParticipants;
// Revamp token ("burn" target)
IERC20 public revampToken;
address public tokenCollector;
// ββββββββββββββ MIGRATION: INITIAL PARTICIPANTS ββββββββββββββ
bool public initialParticipantsLoaded;
function addInitialParticipants(
address[] calldata addrs,
uint256[] calldata contributed
) external onlyOwner {
require(!initialParticipantsLoaded, "Already loaded");
require(addrs.length == contributed.length, "Length mismatch");
require(addrs.length > 0, "Empty input");
uint256 _sumContrib = 0;
for (uint256 i = 0; i < addrs.length; i++) {
address user = addrs[i];
uint256 contrib = contributed[i];
require(user != address(0), "Zero address");
require(contrib > 0, "Zero contrib");
UserInfo storage u = users[user];
require(u.totalContributed == 0, "Already set");
u.totalContributed = contrib;
u.rewardDebt = (contrib * accRewardPerShare) / PRECISION;
_sumContrib += contrib;
_updateTopParticipants(user);
}
totalNativeContributed += _sumContrib;
initialParticipantsLoaded = true;
}
// ββββββββββββββ Events ββββββββββββββ
event AssetListed(address indexed token, uint256 rate, string logoUrl, uint8 decimals, string name, string symbol, uint256 feePaid);
event TokenDelisted(address indexed token, address indexed caller, uint256 feePaid);
event Revamped(address indexed user, address indexed token, uint256 tokenAmount, uint256 nativeAmount);
event WithdrawDone(address indexed user, uint256 withdrawnAmount);
event Claimed(address indexed user, uint256 amount);
event Reinvested(address indexed user, uint256 amount);
event TokenMetadataUpdated(address indexed token, string newLogoUrl, uint256 newRate);
event ListingFeeUpdated(uint256 newFee);
event DelistFeeUpdated(uint256 newFee);
event ClaimFeeUpdated(uint256 newFee);
event NativeFeeUpdated(uint256 newNativeFeePercent, address newNativeFeeRecipient);
event ShareholdingFeeUpdated(uint256 newShareholdingFeePercent, address newShareholdingFeeRecipient);
event FastLineFeeUpdated(uint256 newFeePercent, address newRecipient);
event FastLineFeePaid(address indexed payer, address indexed recipient, uint256 amount); // βοΈ NEW
event RevampTokensLocked(address indexed user, uint256 amount);
event TokenCollectorUpdated(address indexed newCollector);
event ReferralRegistered(address indexed user, address indexed referrer);
event ReferralRewardPaid(address indexed user, address indexed referrer, uint256 amount);
event ReferralFeeUpdated(uint256 newFeePercent);
event GenesisAddressUpdated(address newGenesis);
event MaxContributionPerWalletUpdated(uint256 newMax);
// ββββββββββββββ Constructor ββββββββββββββ
constructor(
uint256 _listingFee,
address _feeRecipient,
uint256 _claimFee,
uint256 _nativeFeePercent,
address _nativeFeeRecipient,
uint256 _shareholdingFeePercent,
address _shareholdingFeeRecipient,
uint256 _fastLineFeePercent,
address _fastLineFeeRecipient,
address _revampToken,
uint256 _delistFee,
uint256 _referralFeePercent,
address _genesisAddress,
uint256 _maxContributionPerWallet
) Ownable(msg.sender) {
require(_feeRecipient != address(0), "Invalid fee recipient");
require(_nativeFeeRecipient != address(0), "Invalid native fee recipient");
require(_shareholdingFeeRecipient != address(0), "Invalid shareholding fee recipient");
require(_revampToken != address(0), "Invalid revamp token");
require(_genesisAddress != address(0), "Invalid genesis");
listingFee = _listingFee;
delistFee = _delistFee;
feeRecipient = _feeRecipient;
claimFee = _claimFee;
nativeFeePercent = _nativeFeePercent;
nativeFeeRecipient = _nativeFeeRecipient;
shareholdingFeePercent = _shareholdingFeePercent;
shareholdingFeeRecipient = _shareholdingFeeRecipient;
require(_fastLineFeeRecipient != address(0), "Invalid fast line recipient");
fastLineFeePercent = _fastLineFeePercent;
fastLineFeeRecipient = _fastLineFeeRecipient;
revampToken = IERC20(_revampToken);
referralFeePercent = _referralFeePercent;
genesisAddress = _genesisAddress;
maxContributionPerWallet = _maxContributionPerWallet;
}
// ββββββββββββββ Cap Management ββββββββββββββ
/**
* @notice Sets the global per-wallet contribution cap (native currency)
* @param _max The new cap (set 0 for no cap)
*/
function setMaxContributionPerWallet(uint256 _max) external onlyOwner {
maxContributionPerWallet = _max;
emit MaxContributionPerWalletUpdated(_max);
}
// ββββββββββββββ Referral Management ββββββββββββββ
function updateReferralFeePercent(uint256 newFeePercent) external onlyOwner {
require(newFeePercent <= 10000, "Too high");
referralFeePercent = newFeePercent;
emit ReferralFeeUpdated(newFeePercent);
}
function updateGenesisAddress(address newGenesis) external onlyOwner {
require(newGenesis != address(0), "Zero genesis");
genesisAddress = newGenesis;
emit GenesisAddressUpdated(newGenesis);
}
// ββββββββββββββ Listing Logic ββββββββββββββ
function listNewAsset(
address token,
uint256 rate,
string calldata logoUrl
) external payable nonReentrant {
require(msg.value >= listingFee, "Fee too low");
require(rate > 0, "Rate > 0");
require(token != address(0), "Bad token");
require(tokenInfos[token].lister == address(0), "Already listed");
IERC20Metadata erc = IERC20Metadata(token);
uint8 _decimals = erc.decimals();
string memory _name = erc.name();
string memory _symbol = erc.symbol();
tokenInfos[token] = TokenInfo({
rate: rate,
lister: msg.sender,
logoUrl: logoUrl,
decimals: _decimals,
name: _name,
symbol: _symbol
});
listedTokens.push(token);
totalListingFees += msg.value;
(bool success, ) = feeRecipient.call{value: msg.value}("");
require(success, "Fee transfer fail");
emit AssetListed(token, rate, logoUrl, _decimals, _name, _symbol, msg.value);
}
function delistAsset(address token) external payable nonReentrant {
TokenInfo storage info = tokenInfos[token];
require(info.lister != address(0), "Asset not listed");
require(msg.value >= delistFee, "Insufficient delist fee");
totalListingFees += msg.value;
(bool success, ) = feeRecipient.call{value: msg.value}("");
require(success, "Fee transfer fail");
delete tokenInfos[token];
for (uint256 i = 0; i < listedTokens.length; i++) {
if (listedTokens[i] == token) {
listedTokens[i] = listedTokens[listedTokens.length - 1];
listedTokens.pop();
break;
}
}
emit TokenDelisted(token, msg.sender, msg.value);
}
// ββββββββββββββ Revamp / Referral / Reward Logic ββββββββββββββ
function revamp(address token, uint256 tokenAmount, address referral) external payable nonReentrant {
TokenInfo storage info = tokenInfos[token];
require(info.lister != address(0), "Asset not listed");
require(tokenAmount > 0, "Tokens > 0");
require(msg.value > 0, "Native > 0");
require(info.decimals > 0 && info.decimals <= 77, "Bad decimals");
// Cap check
if (maxContributionPerWallet > 0) {
require(
users[msg.sender].totalContributed + msg.value <= maxContributionPerWallet,
"Contribution exceeds per-wallet cap"
);
}
IERC20(token).safeTransferFrom(msg.sender, address(this), tokenAmount);
// Set referral if first time
if (referrerOf[msg.sender] == address(0)) {
address actualRef = (referral != address(0) && referral != msg.sender)
? referral
: genesisAddress;
referrerOf[msg.sender] = actualRef;
emit ReferralRegistered(msg.sender, actualRef);
}
address ref = referrerOf[msg.sender];
// Fee calculations and allocations
uint256 nativeFee = (msg.value * nativeFeePercent) / 10000;
uint256 shareFee = (msg.value * shareholdingFeePercent) / 10000;
uint256 referralFee = (msg.value * referralFeePercent) / 10000;
uint256 fastLineFee = (msg.value * fastLineFeePercent) / 10000;
uint256 netValue = msg.value - nativeFee - shareFee - referralFee - fastLineFee;
if (totalNativeContributed > 0) {
accRewardPerShare += (netValue * PRECISION) / totalNativeContributed;
}
UserInfo storage user = users[msg.sender];
user.totalContributed += netValue;
totalNativeContributed += netValue;
user.rewardDebt = (user.totalContributed * accRewardPerShare) / PRECISION;
_updateTopParticipants(msg.sender);
if (nativeFee > 0) {
(bool successNative, ) = nativeFeeRecipient.call{value: nativeFee}("");
require(successNative, "Native fee fail");
}
if (shareFee > 0) {
(bool successShare, ) = shareholdingFeeRecipient.call{value: shareFee}("");
require(successShare, "Share fee fail");
}
if (referralFee > 0 && ref != address(0)) {
(bool successRef, ) = payable(ref).call{value: referralFee}("");
require(successRef, "Referral pay fail");
emit ReferralRewardPaid(msg.sender, ref, referralFee);
}
if (fastLineFee > 0) {
totalFastLineFees += fastLineFee; // βοΈ TRACK SUM
(bool successFast, ) = fastLineFeeRecipient.call{value: fastLineFee}("");
require(successFast, "Fast line fee fail");
emit FastLineFeePaid(msg.sender, fastLineFeeRecipient, fastLineFee); // βοΈ LOG
}
emit Revamped(msg.sender, token, tokenAmount, netValue);
}
function withdraw(uint256 amount) public nonReentrant {
require(amount > 0, "Amt > 0");
UserInfo storage user = users[msg.sender];
require(user.totalContributed > 0, "No principal");
uint256 pending = pendingReward(msg.sender);
uint256 fromReward;
uint256 fromPrincipal = 0;
if (pending >= amount) {
fromReward = amount;
} else {
fromReward = pending;
fromPrincipal = amount - pending;
}
require(fromPrincipal <= user.totalContributed, "Exceeds bal");
uint256 feePart = 0;
if (fromReward > 0) {
require(fromReward > claimFee, "Claim fee high");
feePart = claimFee;
}
uint256 toUser = (fromReward - feePart) + fromPrincipal;
user.claimedSoFar += fromReward;
if (fromPrincipal > 0) {
user.totalContributed -= fromPrincipal;
totalNativeContributed -= fromPrincipal;
}
user.rewardDebt = (user.totalContributed * accRewardPerShare) / PRECISION;
if (feePart > 0) {
(bool feeOk, ) = feeRecipient.call{value: feePart}("");
require(feeOk, "Fee tx fail");
}
(bool ok, ) = payable(msg.sender).call{value: toUser}("");
require(ok, "Withdraw tx fail");
emit WithdrawDone(msg.sender, amount);
}
function claim() external {
uint256 pending = pendingReward(msg.sender);
require(pending > 0, "No pending");
withdraw(pending);
emit Claimed(msg.sender, pending);
}
function reinvest() external nonReentrant {
uint256 pending = pendingReward(msg.sender);
require(pending > 0, "No pending");
UserInfo storage user = users[msg.sender];
user.claimedSoFar += pending;
user.totalContributed += pending;
totalNativeContributed += pending;
user.rewardDebt = (user.totalContributed * accRewardPerShare) / PRECISION;
emit Reinvested(msg.sender, pending);
}
function pendingReward(address userAddr) public view returns (uint256) {
UserInfo storage user = users[userAddr];
uint256 accumulated = (user.totalContributed * accRewardPerShare) / PRECISION;
uint256 rawPending = accumulated > user.rewardDebt ? accumulated - user.rewardDebt : 0;
uint256 maxReward = (user.totalContributed * 215) / 100; // 2.15x cap
uint256 used = user.claimedSoFar;
if (used >= maxReward) return 0;
uint256 leftover = maxReward - used;
return rawPending > leftover ? leftover : rawPending;
}
/*βββββββββββββββββββββββββββββββββββββββββββββ
β TOP PARTICIPANT TRACKING
ββββββββββββββββββββββββββββββββββββββββββββββ*/
function _updateTopParticipants(address userAddr) internal {
bool exists = false;
uint256 len = topParticipants.length;
for (uint256 i = 0; i < len; i++) {
if (topParticipants[i] == userAddr) {
exists = true;
break;
}
}
if (!exists) {
topParticipants.push(userAddr);
}
// Bubble sort: descending order
for (uint256 i = 0; i < topParticipants.length; i++) {
for (uint256 j = i + 1; j < topParticipants.length; j++) {
if (users[topParticipants[j]].totalContributed > users[topParticipants[i]].totalContributed) {
address temp = topParticipants[i];
topParticipants[i] = topParticipants[j];
topParticipants[j] = temp;
}
}
}
if (topParticipants.length > 20) {
topParticipants.pop();
}
}
function getTopParticipants() external view returns (address[] memory addrs, uint256[] memory amounts) {
uint256 len = topParticipants.length;
addrs = new address[](len);
amounts = new uint256[](len);
for (uint256 i = 0; i < len; i++) {
addrs[i] = topParticipants[i];
amounts[i] = users[topParticipants[i]].totalContributed;
}
}
/*βββββββββββββββββββββββββββββββββββββββββββββ
β VIEW / DATA HELPERS
ββββββββββββββββββββββββββββββββββββββββββββββ*/
function getAllListedTokens() external view returns (TokenData[] memory) {
uint256 len = listedTokens.length;
TokenData[] memory arr = new TokenData[](len);
for (uint256 i = 0; i < len; i++) {
address t = listedTokens[i];
TokenInfo storage info = tokenInfos[t];
arr[i] = TokenData({
token: t,
rate: info.rate,
lister: info.lister,
logoUrl: info.logoUrl,
decimals: info.decimals,
name: info.name,
symbol: info.symbol
});
}
return arr;
}
/*βββββββββββββββββββββββββββββββββββββββββββββ
β ADMIN FUNCTIONS (FEES/CONFIG/ETC)
ββββββββββββββββββββββββββββββββββββββββββββββ*/
function updateListingFee(uint256 newFee) external onlyOwner {
listingFee = newFee;
emit ListingFeeUpdated(newFee);
}
function updateDelistFee(uint256 newFee) external onlyOwner {
delistFee = newFee;
emit DelistFeeUpdated(newFee);
}
function updateClaimFee(uint256 newFee) external onlyOwner {
claimFee = newFee;
emit ClaimFeeUpdated(newFee);
}
function updateNativeFee(uint256 newNativeFeePercent, address newRecipient) external onlyOwner {
nativeFeePercent = newNativeFeePercent;
nativeFeeRecipient = newRecipient;
emit NativeFeeUpdated(newNativeFeePercent, newRecipient);
}
function updateShareholdingFee(uint256 newShareholdingFeePercent, address newRecipient) external onlyOwner {
shareholdingFeePercent = newShareholdingFeePercent;
shareholdingFeeRecipient = newRecipient;
emit ShareholdingFeeUpdated(newShareholdingFeePercent, newRecipient);
}
function updateFastLineFee(uint256 newFeePercent, address newRecipient) external onlyOwner {
require(newRecipient != address(0), "Invalid address");
fastLineFeePercent = newFeePercent;
fastLineFeeRecipient = newRecipient;
emit FastLineFeeUpdated(newFeePercent, newRecipient);
}
function exportVitalData() external view onlyOwner returns (
uint256 _totalNativeContributed,
uint256 _accRewardPerShare,
uint256 _totalListingFees
) {
_totalNativeContributed = totalNativeContributed;
_accRewardPerShare = accRewardPerShare;
_totalListingFees = totalListingFees;
}
function updateMyTokenMetadata(address token, string calldata newLogoUrl, uint256 newRate) external nonReentrant {
TokenInfo storage info = tokenInfos[token];
require(info.lister != address(0), "Asset not listed");
require(info.lister == msg.sender, "Not lister");
info.logoUrl = newLogoUrl;
info.rate = newRate;
emit TokenMetadataUpdated(token, newLogoUrl, newRate);
}
// Revamp token collector/lock
function updateTokenCollector(address newCollector) external onlyOwner {
require(newCollector != address(0), "Invalid collector");
tokenCollector = newCollector;
emit TokenCollectorUpdated(newCollector);
}
function lockRevampTokens(uint256 amount) external nonReentrant {
require(amount > 0, "Amt > 0");
require(tokenCollector != address(0), "No collector set");
revampToken.safeTransferFrom(msg.sender, tokenCollector, amount);
emit RevampTokensLocked(msg.sender, amount);
}
/*βββββββββββββββββββββββββββββββββββββββββββββ
β RECEIVE NATIVE FALLBACK
ββββββββββββββββββββββββββββββββββββββββββββββ*/
receive() external payable {}
/*βββββββββββββββββββββββββββββββββββββββββββββ
β OWNER RENOUNCE: IMMUTABLE MODE
ββββββββββββββββββββββββββββββββββββββββββββββ*/
function renounceTrustless() external onlyOwner {
renounceOwnership();
// This makes contract βtrustless trustβ (immutable): all owner-only functions disabled.
}
}
Last updated