MultiSigBoosterPro

Description:

Smart contract deployed on Ethereum with Factory features.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "contracts/booster/pro/MultiSigBoosterPro.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;

import "../../interface/IBoosterPro.sol";

/// @title MultiSigBoosterPro
contract MultiSigBoosterPro {

    address[3] public admins;
    IBoosterPro public boosterPro;

    mapping(bytes32 => mapping(address => bool)) public approvals;

    bytes32 public currentPendingAction;
    uint8 public approvalCount;

    /// @dev Errors
    error NotAdmin();
    error AlreadyApproved();
    error InsufficientApprovals();
    error InvalidAdminIndex();
    error AdminExists();
    error ZeroAddress();

    /// @dev Events
    event AdminUpdated(uint256 indexed index, address oldAdmin, address newAdmin);
    event ActionApproved(bytes32 indexed actionId, address indexed admin, uint8 count);
    event EmergencyWithdrawToken(address indexed to, uint256 amount);
    event EmergencyWithdrawBonds(address to, uint256[] tokenIds);

    modifier onlyAdmins() {
        if (msg.sender != admins[0] && msg.sender != admins[1] && msg.sender != admins[2]) revert NotAdmin();
        _;
    }

    constructor(address _admin1, address _admin2, address _admin3, address _boosterPro) {
        admins = [_admin1, _admin2, _admin3];
        boosterPro = IBoosterPro(_boosterPro);
    }

    function _approveAction(bytes32 actionId) internal {
        if (approvals[actionId][msg.sender]) revert AlreadyApproved();
        approvals[actionId][msg.sender] = true;
        approvalCount += 1;
        emit ActionApproved(actionId, msg.sender, approvalCount);
    }

    function _startAction(bytes32 actionId) internal{
        if (actionId != currentPendingAction) {
            if (currentPendingAction != bytes32(0)) {
                approvals[actionId][admins[0]] = false;
                approvals[actionId][admins[1]] = false;
                approvals[actionId][admins[2]] = false;
            }
            currentPendingAction = actionId;
            approvalCount = 0;
        }
    }

    function _clearAction(bytes32 actionId) internal {
        approvals[actionId][admins[0]] = false;
        approvals[actionId][admins[1]] = false;
        approvals[actionId][admins[2]] = false;
        currentPendingAction = bytes32(0);
        approvalCount = 0;
    }

    function changeAdmin(uint256 index, address newAdmin) external onlyAdmins {
        if (index >= 3) revert InvalidAdminIndex();
        if (newAdmin == address(0)) revert ZeroAddress();
        if (newAdmin == admins[0] || newAdmin == admins[1] || newAdmin == admins[2]) revert AdminExists();

        bytes32 actionId = keccak256(abi.encodePacked("changeAdmin", index, newAdmin));
        _startAction(actionId);
        _approveAction(actionId);

        if (approvalCount == 3) {
            address old = admins[index];
            admins[index] = newAdmin;
            emit AdminUpdated(index, old, newAdmin);
            _clearAction(actionId);
        }
    }

    function emergencyWithdrawToken(address to, uint256 amount) external onlyAdmins {
        if (to != admins[0] && to != admins[1] && to != admins[2]) revert NotAdmin();

        bytes32 actionId = keccak256(abi.encodePacked("emergencyWithdrawToken", to, amount));
        _startAction(actionId);
        _approveAction(actionId);

        if (approvalCount == 2) {
            boosterPro.emergencyWithdrawToken(to, amount);
            emit EmergencyWithdrawToken(to, amount);
            _clearAction(actionId);
        }
    }

    function emergencyWithdrawBonds(address to, uint256[] calldata tokenIds) external onlyAdmins {
        if (to != admins[0] && to != admins[1] && to != admins[2]) revert NotAdmin();

        bytes32 actionId = keccak256(abi.encodePacked("emergencyWithdrawBonds", to, tokenIds));
        _startAction(actionId);
        _approveAction(actionId);

        if (approvalCount == 2) {
            boosterPro.emergencyWithdrawBonds(to, tokenIds);
            emit EmergencyWithdrawBonds(to, tokenIds);
            _clearAction(actionId);
        }
    }

    function setActive(bool enable) external onlyAdmins {
        boosterPro.setActive(enable);
    }

    function setMaxBondsPerAddress(uint256 value) external onlyAdmins {
        boosterPro.setMaxBondsPerAddress(value);
    }

    function setPowers(uint256[3] calldata powers) external onlyAdmins {
        boosterPro.setPowers(powers);
    }

    function setProportionEarn(bool isMin, uint256 value) external onlyAdmins {
        boosterPro.setProportionEarn(isMin, value);
    }

    function setBoostingRate(bool isMin, uint256 value) external onlyAdmins {
        boosterPro.setBoostingRate(isMin, value);
    }

    function setDisableUser(address user, bool disable) external onlyAdmins {
        boosterPro.setDisableUser(user,disable);
    }

    function setIntervalLimit(uint256 value) external onlyAdmins {
        boosterPro.setIntervalLimit(value);
    }

    function setClaimOutFlow(address flow) external onlyAdmins {
        bytes32 actionId = keccak256(abi.encodePacked("setClaimOutFlow", flow));
        _startAction(actionId);
        _approveAction(actionId);

        if (approvalCount == 2) {
            boosterPro.setClaimOutFlow(flow);

            _clearAction(actionId);
        }
    }

    // transfer booster owner
    function transferOwnership(address newOwner) external onlyAdmins {
        bytes32 actionId = keccak256(abi.encodePacked("transferOwnership", newOwner));
        _startAction(actionId);
        _approveAction(actionId);

        if (approvalCount == 2) {
            boosterPro.transferOwnership(newOwner);
            _clearAction(actionId);
        }
    }

}
"
    },
    "contracts/interface/IBoosterPro.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;

interface IBoosterPro {

    function setActive(bool enable) external;
    function setMaxBondsPerAddress(uint256 value) external;
    function setPowers(uint256[3] calldata powers) external;
    function setProportionEarn(bool isMin, uint256 value) external;
    function setBoostingRate(bool isMin, uint256 value) external;
    function setDisableUser(address user, bool disable) external;
    function setIntervalLimit(uint256 value) external;
    function setClaimOutFlow(address flow) external;
    function emergencyWithdrawToken(address to, uint256 amount) external;
    function emergencyWithdrawBonds(address to, uint256[] calldata tokenIds) external;

    function transferOwnership(address newOwner) external;

}
"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 50
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "remappings": [],
    "evmVersion": "istanbul"
  }
}}

Tags:
Factory|addr:0xb6dd8f003d1d903767de2fbd26d37fcc2fb283b8|verified:true|block:23746051|tx:0xb3c64936560772b7fa51af063249086c2270f100f971bc17c91586fe4730a2a1|first_check:1762517032

Submitted on: 2025-11-07 13:03:53

Comments

Log in to comment.

No comments yet.