Contract Name:
MultiSigManager
Contract Source Code:
<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
import "./libs/IMasterChef.sol";
contract MultiSigManager {
address public admin1;
address public admin2;
address public admin3;
IMasterChef public masterChef;
mapping(bytes32 => mapping(address => bool)) public approvals;
bytes32 public currentPendingAction;
event AdminChanged(address oldAdmin, address newAdmin, uint256 adminIndex);
event ActionApproved(bytes32 actionId, address indexed admin);
event EmergencyWithdraw(address indexed token, address indexed to, uint256 amount);
modifier onlyAdmins() {
require(
msg.sender == admin1 || msg.sender == admin2 || msg.sender == admin3,
"Not an admin"
);
_;
}
constructor(address _admin1, address _admin2, address _admin3, address _masterChef) {
masterChef = IMasterChef(_masterChef);
admin1 = _admin1;
admin2 = _admin2;
admin3 = _admin3;
}
function _clearPreviousPendingAction(bytes32 actionId) internal{
if (actionId != currentPendingAction && currentPendingAction != bytes32(0)) {
approvals[currentPendingAction][admin1] = false;
approvals[currentPendingAction][admin2] = false;
approvals[currentPendingAction][admin3] = false;
currentPendingAction = bytes32(0);
}
currentPendingAction = actionId;
}
function _resetPendingAction(bytes32 actionId) internal{
approvals[actionId][admin1] = false;
approvals[actionId][admin2] = false;
approvals[actionId][admin3] = false;
currentPendingAction = bytes32(0);
}
function changeAdmin(address newAdmin, uint256 adminIndex) external onlyAdmins {
require(adminIndex >= 1 && adminIndex <= 3, "Invalid admin index");
require(newAdmin != admin1 && newAdmin != admin2 && newAdmin != admin3, "Invalid newAdmin");
bytes32 actionId = keccak256(abi.encodePacked("changeAdmin", newAdmin, adminIndex));
_clearPreviousPendingAction(actionId);
approvals[actionId][msg.sender] = true;
emit ActionApproved(actionId, msg.sender);
if (_getApprovalCount(actionId) == 3) {
address[3] memory admins = [admin1, admin2, admin3];
address oldAdmin = admins[adminIndex - 1];
if (adminIndex == 1) admin1 = newAdmin;
else if (adminIndex == 2) admin2 = newAdmin;
else if (adminIndex == 3) admin3 = newAdmin;
_resetPendingAction(actionId);
emit AdminChanged(oldAdmin, newAdmin, adminIndex);
}
}
function _getApprovalCount(bytes32 actionId) internal view returns (uint256 count) {
if (approvals[actionId][admin1]) count++;
if (approvals[actionId][admin2]) count++;
if (approvals[actionId][admin3]) count++;
return count;
}
// Emergency withdrawal function
function emergencyWithdraw(address _token, address _to, uint256 _amount) external onlyAdmins {
require(_to == admin1 || _to == admin2 || _to == admin3, "Invalid to address");
bytes32 actionId = keccak256(abi.encodePacked("emergencyWithdraw", _token, _to , _amount));
_clearPreviousPendingAction(actionId);
approvals[actionId][msg.sender] = true;
emit ActionApproved(actionId, msg.sender);
if (_getApprovalCount(actionId) == 2) {
masterChef.emergencyWithdraw(_token, _to, _amount);
_resetPendingAction(actionId);
emit EmergencyWithdraw(_token, _to, _amount);
}
}
// Update the emission rate
function updateEmissionRate(uint256 _daiPerBlock) external onlyAdmins {
masterChef.updateEmissionRate(_daiPerBlock);
}
// Set deposit restriction for an address
function setDepositRestriction(address addr, bool status) external onlyAdmins {
masterChef.setDepositRestriction(addr, status);
}
// Set withdraw restriction for an address
function setWithdrawRestriction(address addr, bool status) external onlyAdmins {
masterChef.setWithdrawRestriction(addr, status);
}
// Set claim restriction for an address
function setClaimRestriction(address addr, bool status) external onlyAdmins {
masterChef.setClaimRestriction(addr, status);
}
// Set charge restriction for an address
function setChargeRestriction(address addr, bool status) external onlyAdmins {
masterChef.setChargeRestriction(addr, status);
}
// Pause or unpause deposits globally
function setDepositPaused(bool status) external onlyAdmins {
masterChef.setDepositPaused(status);
}
// Pause or unpause withdrawals globally
function setWithdrawPaused(bool status) external onlyAdmins {
masterChef.setWithdrawPaused(status);
}
// Pause or unpause claims globally
function setClaimPaused(bool status) external onlyAdmins {
masterChef.setClaimPaused(status);
}
// Set the deposit threshold (in wei)
function setDepositThreshold(uint256 threshold) external onlyAdmins {
masterChef.setDepositThreshold(threshold);
}
// Set the claim threshold (in wei)
function setClaimThreshold(uint256 threshold) external onlyAdmins {
masterChef.setClaimThreshold(threshold);
}
// Set the order locking height (block height)
function setOrderLockingHeight(uint256 height) external onlyAdmins {
masterChef.setOrderLockingHeight(height);
}
// Set the claim charge (percentage)
function setClaimCharge(uint256 charge) external onlyAdmins {
masterChef.setClaimCharge(charge);
}
// Set the commission ratio (percentage)
function setCommissionRatio(uint256 ratio) external onlyAdmins {
masterChef.setCommissionRatio(ratio);
}
// Set the withdrawal charge (percentage)
function setWithdrawalCharge(uint256 charge) external onlyAdmins {
masterChef.setWithdrawalCharge(charge);
}
function setCooldown(uint256 height) external onlyAdmins{
masterChef.setCooldown(height);
}
function setStakingTd(uint level, uint256 threshold) external onlyAdmins{
masterChef.setStakingTd(level, threshold);
}
function setBarkDao(address _barkDao) external onlyAdmins {
masterChef.setBarkDao(_barkDao);
}
function setWhiteListMode(bool _b) external onlyAdmins{
masterChef.setWhiteListMode(_b);
}
function setWhiteList(address _user, bool _b) external onlyAdmins{
masterChef.setWhiteList(_user, _b);
}
// transfer masterChef owner
function transferOwnership(address newOwner) external onlyAdmins {
bytes32 actionId = keccak256(abi.encodePacked("transferOwnership", newOwner));
_clearPreviousPendingAction(actionId);
approvals[actionId][msg.sender] = true;
emit ActionApproved(actionId, msg.sender);
if (_getApprovalCount(actionId) == 2) {
masterChef.transferOwnership(newOwner);
_resetPendingAction(actionId);
}
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
interface IMasterChef {
// Emergency withdrawal function
function emergencyWithdraw(address _token, address _to, uint256 _amount) external;
// Update the emission rate
function updateEmissionRate(uint256 _daiPerBlock) external;
// Set deposit restriction for an address
function setDepositRestriction(address addr, bool status) external;
// Set withdraw restriction for an address
function setWithdrawRestriction(address addr, bool status) external;
// Set claim restriction for an address
function setClaimRestriction(address addr, bool status) external;
// Set charge restriction for an address
function setChargeRestriction(address addr, bool status) external;
// Pause or unpause deposits globally
function setDepositPaused(bool status) external;
// Pause or unpause withdrawals globally
function setWithdrawPaused(bool status) external;
// Pause or unpause claims globally
function setClaimPaused(bool status) external;
// Set the deposit threshold (in wei)
function setDepositThreshold(uint256 threshold) external;
// Set the claim threshold (in wei)
function setClaimThreshold(uint256 threshold) external;
// Set the order locking height (block height)
function setOrderLockingHeight(uint256 height) external;
// Set the claim charge (percentage)
function setClaimCharge(uint256 charge) external;
// Set the commission ratio (percentage)
function setCommissionRatio(uint256 ratio) external;
// Set the withdrawal charge (percentage)
function setWithdrawalCharge(uint256 charge) external;
// transfer owner
function transferOwnership(address newOwner) external;
function setCooldown(uint256 height) external;
function setStakingTd(uint level, uint256 threshold) external;
function setBarkDao(address _barkDao) external;
function setWhiteListMode(bool _b) external;
function setWhiteList(address _user, bool _b) external;
}