Skip to content

Commit

Permalink
fix: check client chain before setPeer
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxMustermann2 committed Jul 30, 2024
1 parent 2b1aa92 commit c01c9a3
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/core/ExocoreGateway.sol
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ contract ExocoreGateway is
onlyOwner
whenNotPaused
{
// The registration of the client chain is done here and nowhere else.
// Elsewhere, the precompile is responsible for the checks. The precompile
// is not called here at all, and hence, such a check must be made manually.
_validateClientChainIdRegistered(clientChainId);
super.setPeer(clientChainId, clientChainGateway);
}

Expand All @@ -176,6 +180,7 @@ contract ExocoreGateway is
string[] calldata names,
string[] calldata metaData
) external payable onlyOwner whenNotPaused nonReentrant {
// The registration of the client chain is left for the precompile to validate.
_validateWhitelistTokensInput(tokens, decimals, tvlLimits, names, metaData);

bool success;
Expand Down Expand Up @@ -274,6 +279,21 @@ contract ExocoreGateway is
}
}

/// @dev Validates that the client chain id is registered.
/// @dev This is designed to be called only in the cases wherein the precompile isn't used.
/// @dev In all other situations, it is the responsibility of the precompile to perform such
/// checks.
/// @param clientChainId The client chain id.
function _validateClientChainIdRegistered(uint32 clientChainId) internal view {
(bool success, bool isRegistered) = ASSETS_CONTRACT.isRegisteredClientChain(clientChainId);
if (!success) {
revert Errors.ExocoreGatewayFailedToCheckClientChainId();
}
if (!isRegistered) {
revert Errors.ExocoreGatewayNotRegisteredClientChainId();
}
}

/// @dev The internal version of registerOrUpdateClientChain.
/// @param clientChainId The client chain id.
/// @param addressLength The length of the address type on the client chain.
Expand Down
6 changes: 6 additions & 0 deletions src/interfaces/precompiles/IAssets.sol
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,10 @@ interface IAssets {
/// @dev Returns the chain indices of the client chains.
function getClientChains() external view returns (bool, uint32[] memory);

/// @dev Checks if the client chain is registered, given the chain ID.
/// @param clientChainID is the layerZero chainID if it is supported.
/// @return success true if the query is successful
/// @return isRegistered true if the client chain is registered
function isRegisteredClientChain(uint32 clientChainID) external view returns (bool success, bool isRegistered);

}
6 changes: 6 additions & 0 deletions src/libraries/Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,12 @@ library Errors {
/// @dev ExocoreGateway: failed to decode client chain ids
error ExocoreGatewayFailedToDecodeClientChainIds();

/// @dev ExocoreGateway: client chain should be registered before.
error ExocoreGatewayNotRegisteredClientChainId();

/// @dev ExocoreGateway: failed to check if the client id is registered
error ExocoreGatewayFailedToCheckClientChainId();

/// @dev ExocoreGateway: thrown when associateOperatorWithEVMStaker failed
error AssociateOperatorFailed(uint32 clientChainId, address staker, string operator);

Expand Down
6 changes: 6 additions & 0 deletions test/foundry/unit/ExocoreGateway.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,12 @@ contract SetPeer is SetUp {
exocoreGateway.setPeer(anotherClientChain, newPeer);
}

function test_RevertWhen_ClientChainNotRegistered() public {
vm.startPrank(exocoreValidatorSet.addr);
vm.expectRevert(Errors.ExocoreGatewayNotRegisteredClientChainId.selector);
exocoreGateway.setPeer(anotherClientChain, newPeer);
}

}

contract AddWhitelistTokens is SetUp {
Expand Down
4 changes: 4 additions & 0 deletions test/mocks/AssetsMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,8 @@ contract AssetsMock is IAssets {
return abi.encodePacked(bytes32(bytes20(addr)));
}

function isRegisteredClientChain(uint32 clientChainID) external view returns (bool, bool) {
return (true, isRegisteredChain[clientChainID]);
}

}
12 changes: 12 additions & 0 deletions test/mocks/ExocoreGatewayMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Own
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import {Errors} from "src/libraries/Errors.sol";
import {OAppCoreUpgradeable} from "src/lzApp/OAppCoreUpgradeable.sol";

contract ExocoreGatewayMock is
Expand Down Expand Up @@ -170,6 +171,7 @@ contract ExocoreGatewayMock is
onlyOwner
whenNotPaused
{
_validateClientChainIdRegistered(clientChainId);
super.setPeer(clientChainId, clientChainGateway);
}

Expand Down Expand Up @@ -243,6 +245,16 @@ contract ExocoreGatewayMock is
}
}

function _validateClientChainIdRegistered(uint32 clientChainId) internal view {
(bool success, bool isRegistered) = ASSETS_CONTRACT.isRegisteredClientChain(clientChainId);
if (!success) {
revert Errors.ExocoreGatewayFailedToCheckClientChainId();
}
if (!isRegistered) {
revert Errors.ExocoreGatewayNotRegisteredClientChainId();
}
}

function _registerOrUpdateClientChain(
uint32 clientChainId,
uint8 addressLength,
Expand Down

0 comments on commit c01c9a3

Please sign in to comment.