Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/core/contracts/external/chainbridge/Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ contract Bridge is Pausable, AccessControl {
_setRoleAdmin(RELAYER_ROLE, DEFAULT_ADMIN_ROLE);

for (uint256 i; i < initialRelayers.length; i++) {
require(!hasRole(RELAYER_ROLE, initialRelayers[i]), "duplicate initial relayer");
grantRole(RELAYER_ROLE, initialRelayers[i]);
_totalRelayers++;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -466,21 +466,24 @@ contract OptimisticOracleV3 is OptimisticOracleV3Interface, Lockable, Ownable, M
return EscalationManagerInterface(em).isDisputeAllowed(assertionId, msg.sender);
}

// Validates if the identifier is whitelisted by first checking the cache. If not whitelisted in the cache then
// checks it from the identifier whitelist contract and caches result.
// Validates the identifier against the live whitelist and caches the current result.
function _validateAndCacheIdentifier(bytes32 identifier) internal returns (bool) {
if (cachedIdentifiers[identifier]) return true;
cachedIdentifiers[identifier] = _getIdentifierWhitelist().isIdentifierSupported(identifier);
return cachedIdentifiers[identifier];
}

// Validates if the currency is whitelisted by first checking the cache. If not whitelisted in the cache then
// checks it from the collateral whitelist contract and caches whitelist status and final fee.
// Validates the currency against the live whitelist. The final fee is fetched only when adding a currency to cache.
function _validateAndCacheCurrency(address currency) internal returns (bool) {
if (cachedCurrencies[currency].isWhitelisted) return true;
cachedCurrencies[currency].isWhitelisted = _getCollateralWhitelist().isOnWhitelist(currency);
cachedCurrencies[currency].finalFee = _getStore().computeFinalFee(currency).rawValue;
return cachedCurrencies[currency].isWhitelisted;
bool isWhitelisted = _getCollateralWhitelist().isOnWhitelist(currency);
if (!isWhitelisted) {
cachedCurrencies[currency].isWhitelisted = false;
return false;
}
if (!cachedCurrencies[currency].isWhitelisted) {
cachedCurrencies[currency].isWhitelisted = true;
cachedCurrencies[currency].finalFee = _getStore().computeFinalFee(currency).rawValue;
}
return true;
}

// Sends assertion resolved callback to the callback recipient and escalation manager (if set).
Expand Down
28 changes: 28 additions & 0 deletions packages/core/test/foundry/external/chainbridge/Bridge.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.0;

import "forge-std/Test.sol";
import "../../../../contracts/external/chainbridge/Bridge.sol";

contract BridgeTest is Test {
function test_TracksUniqueInitialRelayers() public {
address[] memory relayers = new address[](2);
relayers[0] = address(0x1);
relayers[1] = address(0x2);

Bridge bridge = new Bridge(1, relayers, 2, 0, 100);

assertEq(bridge._totalRelayers(), 2);
assertTrue(bridge.isRelayer(relayers[0]));
assertTrue(bridge.isRelayer(relayers[1]));
}

function test_RevertIf_DuplicateInitialRelayer() public {
address[] memory relayers = new address[](2);
relayers[0] = address(0x1);
relayers[1] = address(0x1);

vm.expectRevert("duplicate initial relayer");
new Bridge(1, relayers, 2, 0, 100);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.0;

import "./CommonOptimisticOracleV3Test.sol";

contract OptimisticOracleV3StaleWhitelistCacheTest is CommonOptimisticOracleV3Test {
AddressWhitelist private collateralWhitelist;
IdentifierWhitelist private identifierWhitelist;

function setUp() public {
_commonSetup();
collateralWhitelist = AddressWhitelist(finder.getImplementationAddress(OracleInterfaces.CollateralWhitelist));
identifierWhitelist = IdentifierWhitelist(
finder.getImplementationAddress(OracleInterfaces.IdentifierWhitelist)
);
}

function test_RemovedIdentifierIsRejectedWithoutManualSync() public {
vm.prank(TestAddress.owner);
identifierWhitelist.removeSupportedIdentifier(defaultIdentifier);
assertFalse(identifierWhitelist.isIdentifierSupported(defaultIdentifier));

vm.startPrank(TestAddress.account1);
defaultCurrency.allocateTo(TestAddress.account1, defaultBond);
defaultCurrency.approve(address(optimisticOracleV3), defaultBond);
vm.expectRevert("Unsupported identifier");
optimisticOracleV3.assertTruthWithDefaults(falseClaimAssertion, TestAddress.account1);
vm.stopPrank();
}

function test_RemovedCurrencyIsRejectedWithoutManualSync() public {
vm.prank(TestAddress.owner);
collateralWhitelist.removeFromWhitelist(address(defaultCurrency));
assertFalse(collateralWhitelist.isOnWhitelist(address(defaultCurrency)));

vm.startPrank(TestAddress.account1);
defaultCurrency.allocateTo(TestAddress.account1, defaultBond);
defaultCurrency.approve(address(optimisticOracleV3), defaultBond);
vm.expectRevert("Unsupported currency");
optimisticOracleV3.assertTruthWithDefaults(falseClaimAssertion, TestAddress.account1);
vm.stopPrank();
}
}