Accounts
0x60...110d
0x60...110D

0x60...110D

$500
This contract's source code is verified!
Contract Metadata
Compiler
0.8.26+commit.8a97fa7a
Language
Solidity
Contract Source Code
File 1 of 8: Context.sol
Contract Source Code
File 2 of 8: HeistAchievements.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "@openzeppelin/contracts/access/Ownable.sol";

contract HeistAchievements is Ownable {
    struct Achievement {
        string name;
        string description;
        uint256 requirement;
        uint256 rewardMultiplier;
        bool exists;
    }

    mapping(uint256 => Achievement) public achievements;
    mapping(address => mapping(uint256 => bool)) public userAchievements;
    mapping(address => uint256[]) public userAchievementsList;

    event AchievementUnlocked(address user, uint256 achievementId);
    event AchievementCreated(uint256 achievementId, string name);

    constructor() Ownable(msg.sender) {
        // Initialize default achievements
        createAchievement(
            1,
            "First Time Heister",
            "Complete your first heist",
            1,
            110 // 10% bonus
        );

        createAchievement(
            2,
            "Diamond Hands",
            "Hold through a high-risk event",
            1,
            120 // 20% bonus
        );

        createAchievement(
            3,
            "Master Thief",
            "Complete 10 successful heists",
            10,
            150 // 50% bonus
        );

        createAchievement(
            4,
            "Whale Alert",
            "Stake more than 100,000 SAPU",
            100000 * 10**18,
            200 // 100% bonus
        );

        createAchievement(
            5,
            "OG Crew Member",
            "Participate in heists for over 30 days",
            30 days,
            130 // 30% bonus
        );
    }

    function createAchievement(
        uint256 id,
        string memory name,
        string memory description,
        uint256 requirement,
        uint256 rewardMultiplier
    ) public onlyOwner {
        require(!achievements[id].exists, "Achievement already exists");
        achievements[id] = Achievement(name, description, requirement, rewardMultiplier, true);
        emit AchievementCreated(id, name);
    }

    function unlockAchievement(address user, uint256 achievementId) external onlyOwner {
        require(achievements[achievementId].exists, "Achievement doesn't exist");
        require(!userAchievements[user][achievementId], "Achievement already unlocked");

        userAchievements[user][achievementId] = true;
        userAchievementsList[user].push(achievementId);
        emit AchievementUnlocked(user, achievementId);
    }

    function getUserAchievements(address user) external view returns (uint256[] memory) {
        return userAchievementsList[user];
    }

    function getAchievement(uint256 id) external view returns (Achievement memory) {
        require(achievements[id].exists, "Achievement doesn't exist");
        return achievements[id];
    }
}
Contract Source Code
File 3 of 8: HeistEvents.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "@openzeppelin/contracts/access/Ownable.sol";

contract HeistEvents is Ownable {
    struct Event {
        uint256 startTime;
        uint256 duration;
        uint256 rewardMultiplier;
        uint256 riskLevel;
        bool isActive;
    }

    Event public currentEvent;
    uint256 public constant MIN_DURATION = 1 hours;
    uint256 public constant MAX_DURATION = 24 hours;

    event HeistEventCreated(uint256 startTime, uint256 duration, uint256 rewardMultiplier);
    event HeistEventEnded(uint256 endTime);

    constructor() Ownable(msg.sender) {
    }

    function scheduleEvent(
        uint256 startTime,
        uint256 duration,
        uint256 rewardMultiplier,
        uint256 riskLevel
    ) external onlyOwner {
        require(startTime > block.timestamp, "Start time must be in future");
        require(duration >= MIN_DURATION && duration <= MAX_DURATION, "Invalid duration");
        require(!currentEvent.isActive, "Event already active");

        currentEvent = Event(startTime, duration, rewardMultiplier, riskLevel, true);
        emit HeistEventCreated(startTime, duration, rewardMultiplier);
    }

    function endEvent() external onlyOwner {
        require(currentEvent.isActive, "No active event");
        currentEvent.isActive = false;
        emit HeistEventEnded(block.timestamp);
    }

    function getCurrentMultiplier() public view returns (uint256) {
        if (!currentEvent.isActive) return 100; // Return 1x multiplier
        if (block.timestamp < currentEvent.startTime) return 100;
        if (block.timestamp > currentEvent.startTime + currentEvent.duration) return 100;
        return currentEvent.rewardMultiplier; // Just return the multiplier directly
    }
}
Contract Source Code
File 4 of 8: HeistOperations.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./HeistRoles.sol";
import "./HeistEvents.sol";
import "./HeistAchievements.sol";

interface IHeistAchievements {
    struct Achievement {
        string name;
        uint256 requirement;
        uint256 rewardMultiplier;
        bool exists;
    }
    function getUserAchievements(address user) external view returns (uint256[] memory);
    function getAchievement(uint256 id) external view returns (Achievement memory);
}

contract HeistOperations is Ownable, ReentrancyGuard {
    struct Heist {
        uint256 minStake;
        uint256 maxStake;
        uint256 duration;
        uint256 rewardRate;
        bool active;
    }

    struct UserPosition {
        uint256 amount;
        uint256 startTime;
        uint256 heistTier;
    }

    IERC20 public token;
    HeistRoles public roles;
    HeistEvents public events;
    HeistAchievements public achievements;

    mapping(uint256 => Heist) public heistTiers;
    mapping(address => UserPosition) public userPositions;

    address[] public activeParticipants;
    mapping(address => bool) public isActiveParticipant;
    
    uint256 public constant EARLY_EXIT_PENALTY = 10; // 10% penalty

    uint256 public maxDailyHeists = 100; // Default limit, can be adjusted
    uint256 public dailyHeistCount;
    uint256 public lastResetTimestamp;
    
    uint256 public totalStaked;
    uint256 public constant PRECISION = 1e12;

    event HeistJoined(address user, uint256 amount, uint256 tier);
    event HeistExited(address user, uint256 amount);
    event DailyHeistLimitUpdated(uint256 newLimit);
    

    constructor () Ownable(msg.sender) {
        // Hardcoded addresses - REPLACE THESE WITH YOUR ACTUAL ADDRESSES
        token = IERC20(0xDbB2E40d67C1C5C3119f69282f425d3e7764D6DB);  // SAPU token
        roles = HeistRoles(0x03C8026c6474B8b4fb75c6542420D27c9138a5c3);  // HeistRoles
        events = HeistEvents(0x809b41A349a3d7dDe820dDc69e23BA8a32Fc5743);  // HeistEvents
        achievements = HeistAchievements(0xC233B0AAE8f6A06c6deFd28b1B079497AeF98f73);  // HeistAchievements

        // Short Duration Heists (Hours)
        heistTiers[1] = Heist(
            100 * 10**18,    // 100 SAPU min
            1000 * 10**18,   // 1,000 SAPU max
            4 hours,         // 4 hour duration
            50,              // 50% APR
            true
        );  // Quick Hit

        heistTiers[2] = Heist(
            500 * 10**18,    // 500 SAPU min
            2500 * 10**18,   // 2,500 SAPU max
            12 hours,        // 12 hour duration
            75,              // 75% APR
            true
        );  // Flash Heist

        // Medium Duration Heists (Days)
        heistTiers[3] = Heist(
            1000 * 10**18,   // 1,000 SAPU min
            5000 * 10**18,   // 5,000 SAPU max
            1 days,          // 1 day duration
            100,             // 100% APR
            true
        );  // Bank Job

        heistTiers[4] = Heist(
            2500 * 10**18,   // 2,500 SAPU min
            10000 * 10**18,  // 10,000 SAPU max
            3 days,          // 3 day duration
            150,             // 150% APR
            true
        );  // Vault Raid

        // Long Duration Heists (Weeks)
        heistTiers[5] = Heist(
            5000 * 10**18,   // 5,000 SAPU min
            25000 * 10**18,  // 25,000 SAPU max
            7 days,          // 7 day duration
            200,             // 200% APR
            true
        );  // Diamond Heist

        heistTiers[6] = Heist(
            10000 * 10**18,  // 10,000 SAPU min
            50000 * 10**18,  // 50,000 SAPU max
            14 days,         // 14 day duration
            300,             // 300% APR
            true
        );  // Master Plan
    }

    function setMaxDailyHeists(uint256 _newLimit) external onlyOwner {
        maxDailyHeists = _newLimit;
        emit DailyHeistLimitUpdated(_newLimit);
    }

    // Modify joinHeist function
    function joinHeist(uint256 amount, uint256 tier) external nonReentrant {
        // Check and reset daily counter if needed
        if (block.timestamp >= lastResetTimestamp + 24 hours) {
            dailyHeistCount = 0;
            lastResetTimestamp = block.timestamp;
        }
        
        // Check daily limit
        require(dailyHeistCount < maxDailyHeists, "Daily heist limit reached");
        
        // Original checks
        require(heistTiers[tier].active, "Invalid heist tier");
        require(amount >= heistTiers[tier].minStake, "Below minimum stake");
        require(amount <= heistTiers[tier].maxStake, "Above maximum stake");
        
        UserPosition storage position = userPositions[msg.sender];
        require(position.amount == 0, "Already in a heist");

        token.transferFrom(msg.sender, address(this), amount);
        
        position.amount = amount;
        position.startTime = block.timestamp;
        position.heistTier = tier;

        if (!isActiveParticipant[msg.sender]) {
            activeParticipants.push(msg.sender);
            isActiveParticipant[msg.sender] = true;
        }
        
        dailyHeistCount++; 
        totalStaked += amount;
        
        emit HeistJoined(msg.sender, amount, tier);
    }

    // Add early exit function
    function exitHeistEarly() external nonReentrant {
        UserPosition storage position = userPositions[msg.sender];
        require(position.amount > 0, "No active heist");
        
        uint256 amount = position.amount;
        uint256 penalty = (amount * EARLY_EXIT_PENALTY) / 100;
        
        // Calculate rewards for the actual staking duration
        uint256 rewards = calculateRewards(msg.sender);
        
        position.amount = 0;
        totalStaked -= amount;

        removeFromActiveParticipants(msg.sender);

        // Transfer amount minus penalty plus any accrued rewards
        token.transfer(msg.sender, (amount - penalty) + rewards);
        
        emit HeistExited(msg.sender, (amount - penalty) + rewards);
    }

    function removeFromActiveParticipants(address user) internal {
        if (isActiveParticipant[user]) {
            for (uint i = 0; i < activeParticipants.length; i++) {
                if (activeParticipants[i] == user) {
                    // Move the last element to this position and pop the array
                    activeParticipants[i] = activeParticipants[activeParticipants.length - 1];
                    activeParticipants.pop();
                    isActiveParticipant[user] = false;
                    break;
                }
            }
        }
    }

    function calculateRewards(address user) public view returns (uint256) {
        UserPosition storage position = userPositions[user];
        if (position.amount == 0) return 0;

        uint256 timeStaked = block.timestamp - position.startTime;
        uint256 rewardRate = heistTiers[position.heistTier].rewardRate;
        
        // Simplified calculation:
        // (amount * rewardRate * timeStaked) / (365 days * 100)
        uint256 reward = (position.amount * rewardRate * timeStaked) / (365 days * 100);
        
        return reward;
    }

    function getTotalMultiplier(address user) public view returns (uint256) {
        uint256 totalMultiplier = 100;
        
        // Role multiplier (default to 100 if 0)
        HeistRoles.Role memory userRole = roles.getUserRole(user);
        uint256 roleMultiplier = userRole.rewardMultiplier;
        if (roleMultiplier == 0) roleMultiplier = 100;
        totalMultiplier = totalMultiplier * roleMultiplier / 100;
        
        // Event multiplier
        uint256 eventMultiplier = events.getCurrentMultiplier();
        totalMultiplier = totalMultiplier * eventMultiplier / 100;
        
        uint256[] memory userAchievements = achievements.getUserAchievements(user);
        for (uint i = 0; i < userAchievements.length; i++) {
            IHeistAchievements.Achievement memory achievement = IHeistAchievements(address(achievements)).getAchievement(userAchievements[i]);
            totalMultiplier = totalMultiplier * achievement.rewardMultiplier / 100;
        }
        
        return totalMultiplier;
    }

    // Updated getAllActiveHeists function
    function getAllActiveHeists() external view returns (
        address[] memory users,
        uint256[] memory amounts,
        uint256[] memory tiers,
        uint256[] memory startTimes,
        uint256[] memory endTimes
    ) {
        // Count active heists
        uint256 count = 0;
        for (uint256 i = 0; i < activeParticipants.length; i++) {
            if (userPositions[activeParticipants[i]].amount > 0) {
                count++;
            }
        }
        
        // Initialize arrays
        users = new address[](count);
        amounts = new uint256[](count);
        tiers = new uint256[](count);
        startTimes = new uint256[](count);
        endTimes = new uint256[](count);
        
        // Fill arrays
        uint256 index = 0;
        for (uint256 i = 0; i < activeParticipants.length; i++) {
            address participant = activeParticipants[i];
            UserPosition storage position = userPositions[participant];
            if (position.amount > 0) {
                users[index] = participant;
                amounts[index] = position.amount;
                tiers[index] = position.heistTier;
                startTimes[index] = position.startTime;
                endTimes[index] = position.startTime + heistTiers[position.heistTier].duration;
                index++;
            }
        }
    }

    function updateHeistTier(
        uint256 tier,
        uint256 minStake,
        uint256 maxStake,
        uint256 duration,
        uint256 rewardRate,
        bool active
    ) external onlyOwner {
        heistTiers[tier] = Heist(minStake, maxStake, duration, rewardRate, active);
    }

    function getUserPosition(address user) external view returns (
        uint256 amount,
        uint256 startTime,
        uint256 heistTier,
        uint256 pendingRewards
    ) {
        UserPosition storage position = userPositions[user];
        return (
            position.amount,
            position.startTime,
            position.heistTier,
            calculateRewards(user)
        );
    }

    // Emergency functions
    function emergencyWithdraw() external nonReentrant {
        UserPosition storage position = userPositions[msg.sender];
        require(position.amount > 0, "No stake to withdraw");
        
        uint256 amount = position.amount;
        position.amount = 0;
        totalStaked -= amount;

        removeFromActiveParticipants(msg.sender);
        
        token.transfer(msg.sender, amount);
    }

    function getActiveParticipantsCount() external view returns (uint256) {
        return activeParticipants.length;
    }

    function recoverERC20(address tokenAddress, uint256 amount) external onlyOwner {
        require(tokenAddress != address(token), "Cannot recover staking token");
        IERC20(tokenAddress).transfer(owner(), amount);
    }

    // Regular exit function for completed heists
    function exitHeist() external nonReentrant {
        UserPosition storage position = userPositions[msg.sender];
        require(position.amount > 0, "No active heist");
        require(
            block.timestamp >= position.startTime + heistTiers[position.heistTier].duration,
            "Heist duration not completed"
        );
        
        uint256 amount = position.amount;
        uint256 rewards = calculateRewards(msg.sender);
        
        position.amount = 0;
        totalStaked -= amount;

        removeFromActiveParticipants(msg.sender);

        // Transfer full amount plus rewards (no penalty)
        token.transfer(msg.sender, amount + rewards);
        
        emit HeistExited(msg.sender, amount + rewards);
    }

    // Owner deposit function
    function depositTokens(uint256 amount) external onlyOwner {
        require(amount > 0, "Amount must be greater than 0");
        token.transferFrom(msg.sender, address(this), amount);
    }

    // Owner withdrawal function
    function withdrawTokens(uint256 amount) external onlyOwner {
        require(amount > 0, "Amount must be greater than 0");
        require(
            token.balanceOf(address(this)) - totalStaked >= amount,
            "Cannot withdraw staked tokens"
        );
        token.transfer(msg.sender, amount);
    }

    // Updated debug function to show more human-readable numbers
    function debugRewards(address user) public view returns (
        uint256 timeStaked,
        uint256 rewardRate,
        uint256 blockTime,
        uint256 stakedTokens,
        uint256 rewardTokens
    ) {
        UserPosition storage position = userPositions[user];
        
        timeStaked = block.timestamp - position.startTime;
        rewardRate = heistTiers[position.heistTier].rewardRate;
        
        // Calculate rewards
        uint256 reward = (position.amount * rewardRate * timeStaked) / (365 days * 100);
        
        return (
            timeStaked,
            rewardRate,
            block.timestamp,
            position.amount / 1e18, // Convert to whole tokens
            reward / 1e18  // Convert to whole tokens
        );
    }

}
Contract Source Code
File 5 of 8: HeistRoles.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "@openzeppelin/contracts/access/Ownable.sol";

contract HeistRoles is Ownable {
    struct Role {
        string name;
        uint256 minStake;
        uint256 rewardMultiplier;
        uint256 cooldownPeriod;
    }

    mapping(uint256 => Role) public roles;
    mapping(address => uint256) public userRoles;
    
    uint256 public constant LOOKOUT = 1;
    uint256 public constant SAFECRACKER = 2;
    uint256 public constant MASTERMIND = 3;

    event RoleAssigned(address user, uint256 roleId);
    event RoleUpdated(uint256 roleId, string name, uint256 minStake, uint256 rewardMultiplier);

    constructor() Ownable(msg.sender) {
        // Initialize default roles
        roles[LOOKOUT] = Role("Lookout", 1000 * 10**18, 100, 1 days);
        roles[SAFECRACKER] = Role("Safecracker", 5000 * 10**18, 150, 3 days);
        roles[MASTERMIND] = Role("Mastermind", 10000 * 10**18, 200, 7 days);
    }

    function assignRole(address user, uint256 roleId) external onlyOwner {
        require(roleId > 0 && roleId <= 3, "Invalid role");
        userRoles[user] = roleId;
        emit RoleAssigned(user, roleId);
    }

    function updateRole(
        uint256 roleId,
        string memory name,
        uint256 minStake,
        uint256 rewardMultiplier,
        uint256 cooldownPeriod
    ) external onlyOwner {
        require(roleId > 0 && roleId <= 3, "Invalid role");
        roles[roleId] = Role(name, minStake, rewardMultiplier, cooldownPeriod);
        emit RoleUpdated(roleId, name, minStake, rewardMultiplier);
    }

    function getRole(uint256 roleId) external view returns (Role memory) {
        return roles[roleId];
    }

    function getUserRole(address user) external view returns (Role memory) {
        uint256 roleId = userRoles[user];
        return roles[roleId];
    }
}
Contract Source Code
File 6 of 8: IERC20.sol
Contract Source Code
File 7 of 8: Ownable.sol
Contract Source Code
File 8 of 8: ReentrancyGuard.sol
Settings
{
  "compilationTarget": {
    "contracts/HeistOperations.sol": "HeistOperations"
  },
  "evmVersion": "cancun",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "remappings": [
    ":@openzeppelin/contracts/=./.deps/npm/@openzeppelin/contracts/",
    ":@uniswap/v3-core/=./.deps/npm/@uniswap/v3-core/"
  ]
}
ABI
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newLimit","type":"uint256"}],"name":"DailyHeistLimitUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"HeistExited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tier","type":"uint256"}],"name":"HeistJoined","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"EARLY_EXIT_PENALTY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"achievements","outputs":[{"internalType":"contract HeistAchievements","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"activeParticipants","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"calculateRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dailyHeistCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"debugRewards","outputs":[{"internalType":"uint256","name":"timeStaked","type":"uint256"},{"internalType":"uint256","name":"rewardRate","type":"uint256"},{"internalType":"uint256","name":"blockTime","type":"uint256"},{"internalType":"uint256","name":"stakedTokens","type":"uint256"},{"internalType":"uint256","name":"rewardTokens","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"depositTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"events","outputs":[{"internalType":"contract HeistEvents","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exitHeist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exitHeistEarly","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getActiveParticipantsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllActiveHeists","outputs":[{"internalType":"address[]","name":"users","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"tiers","type":"uint256[]"},{"internalType":"uint256[]","name":"startTimes","type":"uint256[]"},{"internalType":"uint256[]","name":"endTimes","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getTotalMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserPosition","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"heistTier","type":"uint256"},{"internalType":"uint256","name":"pendingRewards","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"heistTiers","outputs":[{"internalType":"uint256","name":"minStake","type":"uint256"},{"internalType":"uint256","name":"maxStake","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"rewardRate","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isActiveParticipant","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tier","type":"uint256"}],"name":"joinHeist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastResetTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxDailyHeists","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"roles","outputs":[{"internalType":"contract HeistRoles","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newLimit","type":"uint256"}],"name":"setMaxDailyHeists","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tier","type":"uint256"},{"internalType":"uint256","name":"minStake","type":"uint256"},{"internalType":"uint256","name":"maxStake","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"rewardRate","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"}],"name":"updateHeistTier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userPositions","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"heistTier","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}]