-
Notifications
You must be signed in to change notification settings - Fork 79
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding Contracts for compilation and change to return result
- Loading branch information
1 parent
781d2d5
commit c5e02ad
Showing
59 changed files
with
4,031 additions
and
155 deletions.
There are no files selected for viewing
204 changes: 204 additions & 0 deletions
204
...s/connectors-gateway/connectors-gateway-axelar-precompile/contracts/AdminMultisigBase.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity 0.8.9; | ||
|
||
import { EternalStorage } from './EternalStorage.sol'; | ||
|
||
/* | ||
* Deprecated. See InterchainGovernance instead. | ||
* AxelarGateway still inherits this to preserve storage layout used by EternalStorage when upgrading. | ||
*/ | ||
contract AdminMultisigBase is EternalStorage { | ||
error NotAdmin(); | ||
error AlreadyVoted(); | ||
error InvalidAdmins(); | ||
error InvalidAdminThreshold(); | ||
error DuplicateAdmin(address admin); | ||
|
||
// AUDIT: slot names should be prefixed with some standard string | ||
bytes32 internal constant KEY_ADMIN_EPOCH = keccak256('admin-epoch'); | ||
|
||
bytes32 internal constant PREFIX_ADMIN = keccak256('admin'); | ||
bytes32 internal constant PREFIX_ADMIN_COUNT = keccak256('admin-count'); | ||
bytes32 internal constant PREFIX_ADMIN_THRESHOLD = keccak256('admin-threshold'); | ||
bytes32 internal constant PREFIX_ADMIN_VOTE_COUNTS = keccak256('admin-vote-counts'); | ||
bytes32 internal constant PREFIX_ADMIN_VOTED = keccak256('admin-voted'); | ||
bytes32 internal constant PREFIX_IS_ADMIN = keccak256('is-admin'); | ||
|
||
// NOTE: Given the early void return, this modifier should be used with care on functions that return data. | ||
modifier onlyAdmin() { | ||
uint256 adminEpoch = _adminEpoch(); | ||
|
||
if (!_isAdmin(adminEpoch, msg.sender)) revert NotAdmin(); | ||
|
||
bytes32 topic = keccak256(msg.data); | ||
|
||
// Check that admin has not voted, then record that they have voted. | ||
if (_hasVoted(adminEpoch, topic, msg.sender)) revert AlreadyVoted(); | ||
|
||
_setHasVoted(adminEpoch, topic, msg.sender, true); | ||
|
||
// Determine the new vote count and update it. | ||
uint256 adminVoteCount = _getVoteCount(adminEpoch, topic) + uint256(1); | ||
_setVoteCount(adminEpoch, topic, adminVoteCount); | ||
|
||
// Do not proceed with operation execution if insufficient votes. | ||
if (adminVoteCount < _getAdminThreshold(adminEpoch)) return; | ||
|
||
_; | ||
|
||
// Clear vote count and voted booleans. | ||
_setVoteCount(adminEpoch, topic, uint256(0)); | ||
|
||
uint256 adminCount = _getAdminCount(adminEpoch); | ||
|
||
for (uint256 i; i < adminCount; ++i) { | ||
_setHasVoted(adminEpoch, topic, _getAdmin(adminEpoch, i), false); | ||
} | ||
} | ||
|
||
/********************\ | ||
|* Pure Key Getters *| | ||
\********************/ | ||
|
||
function _getAdminKey(uint256 adminEpoch, uint256 index) internal pure returns (bytes32) { | ||
return keccak256(abi.encodePacked(PREFIX_ADMIN, adminEpoch, index)); | ||
} | ||
|
||
function _getAdminCountKey(uint256 adminEpoch) internal pure returns (bytes32) { | ||
return keccak256(abi.encodePacked(PREFIX_ADMIN_COUNT, adminEpoch)); | ||
} | ||
|
||
function _getAdminThresholdKey(uint256 adminEpoch) internal pure returns (bytes32) { | ||
return keccak256(abi.encodePacked(PREFIX_ADMIN_THRESHOLD, adminEpoch)); | ||
} | ||
|
||
function _getAdminVoteCountsKey(uint256 adminEpoch, bytes32 topic) internal pure returns (bytes32) { | ||
return keccak256(abi.encodePacked(PREFIX_ADMIN_VOTE_COUNTS, adminEpoch, topic)); | ||
} | ||
|
||
function _getAdminVotedKey( | ||
uint256 adminEpoch, | ||
bytes32 topic, | ||
address account | ||
) internal pure returns (bytes32) { | ||
return keccak256(abi.encodePacked(PREFIX_ADMIN_VOTED, adminEpoch, topic, account)); | ||
} | ||
|
||
function _getIsAdminKey(uint256 adminEpoch, address account) internal pure returns (bytes32) { | ||
return keccak256(abi.encodePacked(PREFIX_IS_ADMIN, adminEpoch, account)); | ||
} | ||
|
||
/***********\ | ||
|* Getters *| | ||
\***********/ | ||
|
||
function _adminEpoch() internal view returns (uint256) { | ||
return getUint(KEY_ADMIN_EPOCH); | ||
} | ||
|
||
function _getAdmin(uint256 adminEpoch, uint256 index) internal view returns (address) { | ||
return getAddress(_getAdminKey(adminEpoch, index)); | ||
} | ||
|
||
function _getAdminCount(uint256 adminEpoch) internal view returns (uint256) { | ||
return getUint(_getAdminCountKey(adminEpoch)); | ||
} | ||
|
||
function _getAdminThreshold(uint256 adminEpoch) internal view returns (uint256) { | ||
return getUint(_getAdminThresholdKey(adminEpoch)); | ||
} | ||
|
||
function _getVoteCount(uint256 adminEpoch, bytes32 topic) internal view returns (uint256) { | ||
return getUint(_getAdminVoteCountsKey(adminEpoch, topic)); | ||
} | ||
|
||
function _hasVoted( | ||
uint256 adminEpoch, | ||
bytes32 topic, | ||
address account | ||
) internal view returns (bool) { | ||
return getBool(_getAdminVotedKey(adminEpoch, topic, account)); | ||
} | ||
|
||
function _isAdmin(uint256 adminEpoch, address account) internal view returns (bool) { | ||
return getBool(_getIsAdminKey(adminEpoch, account)); | ||
} | ||
|
||
/***********\ | ||
|* Setters *| | ||
\***********/ | ||
|
||
function _setAdminEpoch(uint256 adminEpoch) internal { | ||
_setUint(KEY_ADMIN_EPOCH, adminEpoch); | ||
} | ||
|
||
function _setAdmin( | ||
uint256 adminEpoch, | ||
uint256 index, | ||
address account | ||
) internal { | ||
_setAddress(_getAdminKey(adminEpoch, index), account); | ||
} | ||
|
||
function _setAdminCount(uint256 adminEpoch, uint256 adminCount) internal { | ||
_setUint(_getAdminCountKey(adminEpoch), adminCount); | ||
} | ||
|
||
function _setAdmins( | ||
uint256 adminEpoch, | ||
address[] memory accounts, | ||
uint256 threshold | ||
) internal { | ||
uint256 adminLength = accounts.length; | ||
|
||
if (adminLength < threshold) revert InvalidAdmins(); | ||
|
||
if (threshold == uint256(0)) revert InvalidAdminThreshold(); | ||
|
||
_setAdminThreshold(adminEpoch, threshold); | ||
_setAdminCount(adminEpoch, adminLength); | ||
|
||
for (uint256 i; i < adminLength; ++i) { | ||
address account = accounts[i]; | ||
|
||
// Check that the account wasn't already set as an admin for this epoch. | ||
if (_isAdmin(adminEpoch, account)) revert DuplicateAdmin(account); | ||
|
||
if (account == address(0)) revert InvalidAdmins(); | ||
|
||
// Set this account as the i-th admin in this epoch (needed to we can clear topic votes in `onlyAdmin`). | ||
_setAdmin(adminEpoch, i, account); | ||
_setIsAdmin(adminEpoch, account, true); | ||
} | ||
} | ||
|
||
function _setAdminThreshold(uint256 adminEpoch, uint256 adminThreshold) internal { | ||
_setUint(_getAdminThresholdKey(adminEpoch), adminThreshold); | ||
} | ||
|
||
function _setVoteCount( | ||
uint256 adminEpoch, | ||
bytes32 topic, | ||
uint256 voteCount | ||
) internal { | ||
_setUint(_getAdminVoteCountsKey(adminEpoch, topic), voteCount); | ||
} | ||
|
||
function _setHasVoted( | ||
uint256 adminEpoch, | ||
bytes32 topic, | ||
address account, | ||
bool voted | ||
) internal { | ||
_setBool(_getAdminVotedKey(adminEpoch, topic, account), voted); | ||
} | ||
|
||
function _setIsAdmin( | ||
uint256 adminEpoch, | ||
address account, | ||
bool isAdmin | ||
) internal { | ||
_setBool(_getIsAdminKey(adminEpoch, account), isAdmin); | ||
} | ||
} |
Oops, something went wrong.