diff --git a/packages/evm/contracts/interfaces/IAdapter.sol b/packages/evm/contracts/interfaces/IAdapter.sol index 11ecb4f7..72498484 100644 --- a/packages/evm/contracts/interfaces/IAdapter.sol +++ b/packages/evm/contracts/interfaces/IAdapter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity ^0.8.20; +pragma solidity ^0.8.0; /** * @title IAdapter diff --git a/packages/evm/contracts/interfaces/IBlockHashAdapter.sol b/packages/evm/contracts/interfaces/IBlockHashAdapter.sol index 9073c05b..a6a27ed6 100644 --- a/packages/evm/contracts/interfaces/IBlockHashAdapter.sol +++ b/packages/evm/contracts/interfaces/IBlockHashAdapter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity ^0.8.20; +pragma solidity ^0.8.0; import { IAdapter } from "./IAdapter.sol"; diff --git a/packages/evm/contracts/interfaces/IGiriGiriBashi.sol b/packages/evm/contracts/interfaces/IGiriGiriBashi.sol index 2b917028..403d757c 100644 --- a/packages/evm/contracts/interfaces/IGiriGiriBashi.sol +++ b/packages/evm/contracts/interfaces/IGiriGiriBashi.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity ^0.8.20; +pragma solidity ^0.8.0; import { IAdapter } from "./IAdapter.sol"; import { IHashi } from "./IHashi.sol"; @@ -23,9 +23,10 @@ interface IGiriGiriBashi is IShuSho { uint256 timeout; // grace period in which the adapter must report on an in-range id after being challenged. } + error AdaptersCannotContainChallengedAdapter(IAdapter[] adapters, IAdapter adapter); error AdapterHasNotYetTimedOut(IAdapter adapter); error AdapterNotQuarantined(IAdapter adapter); - error AdaptersAgreed(IAdapter adapter1, IAdapter adapter2); + error AdaptersAgreed(); error AlreadyQuarantined(IAdapter adapter); error CannotProveNoConfidence(uint256 domain, uint256 id, IAdapter[] adapters); error ChallengeNotFound(bytes32 challengeId, uint256 domain, uint256 id, IAdapter adapter); @@ -143,6 +144,13 @@ interface IGiriGiriBashi is IShuSho { */ function enableAdapters(uint256 domain, IAdapter[] memory adapters, Settings[] memory settings) external; + /** + * @dev Get the current challenge given a challengeId. + * @param challengeId - The Bytes32 identifier for the challenge. + * @return challenge - Challenge indicating the challenge parameters. + */ + function getChallenge(bytes32 challengeId) external view returns (Challenge memory); + /** * @dev Gets the challenge ID for a given domain, ID, and adapter. * @param domain - The Uint256 identifier for the domain. @@ -152,6 +160,13 @@ interface IGiriGiriBashi is IShuSho { */ function getChallengeId(uint256 domain, uint256 id, IAdapter adapter) external pure returns (bytes32); + /** + * @dev Get how far beyond the current highestId can be challenged. + * @param domain - The Uint256 identifier for the domain. + * @return range - Uint256 indicating the challenge range. + */ + function getChallengeRange(uint256 domain) external view returns (uint256); + /** * @dev Returns the hash agreed upon by a threshold of the enabled adapters. * @param domain - Uint256 identifier for the domain to query. @@ -187,6 +202,21 @@ interface IGiriGiriBashi is IShuSho { */ function getHash(uint256 domain, uint256 id, IAdapter[] memory adapters) external returns (bytes32); + /** + * @dev Returns the highest id reported for a given id + * @param domain - Uint256 identifier for the domain to query. + * @return id - Uint256 indicating the highest id reported. + */ + function getHead(uint256 domain) external view returns (uint256); + + /** + * @dev Get the current settings for a given adapter. + * @param domain - Uint256 identifier for the domain to query. + * @param adapter - The adapter. + * @return settings - The Settings for the given adapter. + */ + function getSettings(uint256 domain, IAdapter adapter) external view returns (Settings memory); + /** * @dev Replaces the quarantined adapters for a given domain with new adapters and settings. * @param domain - The Uint256 identifier for the domain. diff --git a/packages/evm/contracts/interfaces/IHashi.sol b/packages/evm/contracts/interfaces/IHashi.sol index fa883171..9af2e961 100644 --- a/packages/evm/contracts/interfaces/IHashi.sol +++ b/packages/evm/contracts/interfaces/IHashi.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity ^0.8.20; +pragma solidity ^0.8.0; import { IAdapter } from "./IAdapter.sol"; diff --git a/packages/evm/contracts/interfaces/IHeaderStorage.sol b/packages/evm/contracts/interfaces/IHeaderStorage.sol index 126857b2..5da04a3d 100644 --- a/packages/evm/contracts/interfaces/IHeaderStorage.sol +++ b/packages/evm/contracts/interfaces/IHeaderStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity ^0.8.20; +pragma solidity ^0.8.0; /** * @title IHeaderStorage diff --git a/packages/evm/contracts/interfaces/IJushin.sol b/packages/evm/contracts/interfaces/IJushin.sol index 55aecb03..a8df2c76 100644 --- a/packages/evm/contracts/interfaces/IJushin.sol +++ b/packages/evm/contracts/interfaces/IJushin.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity ^0.8.20; +pragma solidity ^0.8.0; /** * @title IJushin diff --git a/packages/evm/contracts/interfaces/IMessage.sol b/packages/evm/contracts/interfaces/IMessage.sol index 9ec02029..47babcc8 100644 --- a/packages/evm/contracts/interfaces/IMessage.sol +++ b/packages/evm/contracts/interfaces/IMessage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity ^0.8.20; +pragma solidity ^0.8.0; import { IReporter } from "./IReporter.sol"; import { IAdapter } from "./IAdapter.sol"; diff --git a/packages/evm/contracts/interfaces/IMessageHashCalculator.sol b/packages/evm/contracts/interfaces/IMessageHashCalculator.sol index acb10fd8..24a41ef3 100644 --- a/packages/evm/contracts/interfaces/IMessageHashCalculator.sol +++ b/packages/evm/contracts/interfaces/IMessageHashCalculator.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity ^0.8.20; +pragma solidity ^0.8.0; import { Message } from "./IMessage.sol"; diff --git a/packages/evm/contracts/interfaces/IMessageIdCalculator.sol b/packages/evm/contracts/interfaces/IMessageIdCalculator.sol index ee818fec..0cfefee8 100644 --- a/packages/evm/contracts/interfaces/IMessageIdCalculator.sol +++ b/packages/evm/contracts/interfaces/IMessageIdCalculator.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity ^0.8.20; +pragma solidity ^0.8.0; /** * @title IMessageIdCalculator diff --git a/packages/evm/contracts/interfaces/IReporter.sol b/packages/evm/contracts/interfaces/IReporter.sol index ced2048a..6f9ad316 100644 --- a/packages/evm/contracts/interfaces/IReporter.sol +++ b/packages/evm/contracts/interfaces/IReporter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity ^0.8.20; +pragma solidity ^0.8.0; import { IAdapter } from "./IAdapter.sol"; diff --git a/packages/evm/contracts/interfaces/IShoyuBashi.sol b/packages/evm/contracts/interfaces/IShoyuBashi.sol index 15f43f46..96a0ea9e 100644 --- a/packages/evm/contracts/interfaces/IShoyuBashi.sol +++ b/packages/evm/contracts/interfaces/IShoyuBashi.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity ^0.8.20; +pragma solidity ^0.8.0; import { IHashi } from "./IHashi.sol"; import { IAdapter } from "./IAdapter.sol"; diff --git a/packages/evm/contracts/interfaces/IShuSho.sol b/packages/evm/contracts/interfaces/IShuSho.sol index 97feeecf..76f436aa 100644 --- a/packages/evm/contracts/interfaces/IShuSho.sol +++ b/packages/evm/contracts/interfaces/IShuSho.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity ^0.8.20; +pragma solidity ^0.8.0; import { IHashi } from "./IHashi.sol"; import { IAdapter } from "./IAdapter.sol"; @@ -20,10 +20,12 @@ interface IShuSho { error AdapterNotEnabled(IAdapter adapter); error AdapterAlreadyEnabled(IAdapter adapter); + error CountCannotBeZero(); error DuplicateHashiAddress(IHashi hashi); error DuplicateOrOutOfOrderAdapters(IAdapter adapterOne, IAdapter adapterTwo); error DuplicateThreashold(uint256 threshold); error InvalidAdapter(IAdapter adapter); + error InvalidThreshold(uint256 threshold); error NoAdaptersEnabled(uint256 domain); error NoAdaptersGiven(); error ThresholdNotMet(); @@ -69,6 +71,14 @@ interface IShuSho { */ function checkAdapterOrderAndValidity(uint256 domain, IAdapter[] memory _adapters) external view; + /** + * @dev Get the previous and the next adapter given a domain and an adapter. + * @param domain - Uint256 identifier for the domain. + * @param adapter - IAdapter value for the adapter. + * @return link - The Link struct containing the previous and the next adapter. + */ + function getAdapterLink(uint256 domain, IAdapter adapter) external view returns (Link memory); + /** * @dev Returns an array of enabled adapters for a given domain. * @param domain - Uint256 identifier for the domain for which to list adapters. @@ -76,6 +86,13 @@ interface IShuSho { */ function getAdapters(uint256 domain) external view returns (IAdapter[] memory); + /** + * @dev Get the current configuration for a given domain. + * @param domain - Uint256 identifier for the domain. + * @return domain - The Domain struct containing the current configuration for a given domain. + */ + function getDomain(uint256 domain) external view returns (Domain memory); + /** * @dev Returns the threshold and count for a given domain. * @param domain - Uint256 identifier for the domain. @@ -84,4 +101,10 @@ interface IShuSho { * @notice If the threshold for a domain has not been set, or is explicitly set to 0, this function will return a threshold equal to the adapters count for the given domain. */ function getThresholdAndCount(uint256 domain) external view returns (uint256, uint256); + + /** + * @dev Returns the address of the specified Hashi. + * @return hashi - The Hashi address. + */ + function hashi() external view returns (IHashi); } diff --git a/packages/evm/contracts/interfaces/IYaho.sol b/packages/evm/contracts/interfaces/IYaho.sol index b6d780ec..46f8edc1 100644 --- a/packages/evm/contracts/interfaces/IYaho.sol +++ b/packages/evm/contracts/interfaces/IYaho.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity ^0.8.20; +pragma solidity ^0.8.0; import { IMessageHashCalculator } from "./IMessageHashCalculator.sol"; import { IMessageIdCalculator } from "./IMessageIdCalculator.sol"; diff --git a/packages/evm/contracts/interfaces/IYaru.sol b/packages/evm/contracts/interfaces/IYaru.sol index 77258293..150c62fe 100644 --- a/packages/evm/contracts/interfaces/IYaru.sol +++ b/packages/evm/contracts/interfaces/IYaru.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity ^0.8.20; +pragma solidity ^0.8.0; import { Message } from "./IMessage.sol"; import { IMessageHashCalculator } from "./IMessageHashCalculator.sol"; diff --git a/packages/evm/contracts/ownable/GiriGiriBashi.sol b/packages/evm/contracts/ownable/GiriGiriBashi.sol index fd06d8ae..2b296413 100644 --- a/packages/evm/contracts/ownable/GiriGiriBashi.sol +++ b/packages/evm/contracts/ownable/GiriGiriBashi.sol @@ -7,49 +7,51 @@ import { IHashi } from "../interfaces/IHashi.sol"; import { IGiriGiriBashi } from "../interfaces/IGiriGiriBashi.sol"; contract GiriGiriBashi is IGiriGiriBashi, ShuSo { - address payable public bondRecipient; // address that bonds from unsuccessful challenges should be sent to. - mapping(uint256 => uint256) public heads; // highest Id reported. - mapping(uint256 => uint256) public challengeRanges; // how far beyond the current highestId can a challenged. - mapping(IAdapter => Settings) public settings; - mapping(bytes32 => Challenge) public challenges; // current challenges. + address payable public bondRecipient; + + mapping(uint256 => uint256) private _heads; + mapping(uint256 => uint256) private _challengeRanges; + mapping(uint256 => mapping(IAdapter => Settings)) private _settings; + mapping(bytes32 => Challenge) private _challenges; constructor(address _owner, address _hashi, address payable _bondRecipient) ShuSo(_owner, _hashi) { bondRecipient = _bondRecipient; } modifier noConfidence(uint256 domain) { - if (domains[domain].threshold != type(uint256).max) revert NoConfidenceRequired(); + if (getDomain(domain).threshold != type(uint256).max) revert NoConfidenceRequired(); _; } modifier zeroCount(uint256 domain) { - if (domains[domain].count != 0) revert CountMustBeZero(domain); + Domain memory domainConfigs = getDomain(domain); + if (domainConfigs.count != 0 && domainConfigs.threshold > 0) revert CountMustBeZero(domain); _; } /// @inheritdoc IGiriGiriBashi function challengeAdapter(uint256 domain, uint256 id, IAdapter adapter) public payable { - if (adapters[domain][adapter].previous == IAdapter(address(0))) revert AdapterNotEnabled(adapter); - if (msg.value < settings[adapter].minimumBond) revert NotEnoughValue(adapter, msg.value); - if (settings[adapter].quarantined) revert AlreadyQuarantined(adapter); + if (getAdapterLink(domain, adapter).previous == IAdapter(address(0))) revert AdapterNotEnabled(adapter); + if (msg.value < _settings[domain][adapter].minimumBond) revert NotEnoughValue(adapter, msg.value); + if (_settings[domain][adapter].quarantined) revert AlreadyQuarantined(adapter); bytes32 challengeId = getChallengeId(domain, id, adapter); - if (challenges[challengeId].challenger != address(0)) + if (_challenges[challengeId].challenger != address(0)) revert DuplicateChallenge(challengeId, domain, id, adapter); // check if id is lower than startId, revert if true. // check if id is less than highestId + challengeRange, revert if false // check if id is lower than highestId - idDepth, revert if true - uint256 challengeRange = challengeRanges[domain]; - uint256 idDepth = settings[adapter].idDepth; - uint256 head = heads[domain]; + uint256 challengeRange = _challengeRanges[domain]; + uint256 idDepth = _settings[domain][adapter].idDepth; + uint256 head = _heads[domain]; if ( - id < settings[adapter].startId || // before start id + id < _settings[domain][adapter].startId || // before start id (challengeRange != 0 && id >= head && id - head > challengeRange) || // over domain challenge range (idDepth != 0 && head > idDepth && id <= head - idDepth) // outside of adapter idDepth ) revert OutOfRange(adapter, id); - Challenge storage challenge = challenges[challengeId]; + Challenge storage challenge = _challenges[challengeId]; challenge.challenger = payable(msg.sender); challenge.timestamp = block.timestamp; challenge.bond = msg.value; @@ -60,40 +62,59 @@ contract GiriGiriBashi is IGiriGiriBashi, ShuSo { /// @inheritdoc IGiriGiriBashi function enableAdapters( uint256 domain, - IAdapter[] memory _adapters, - Settings[] memory _settings + IAdapter[] memory adapters, + Settings[] memory settings ) public zeroCount(domain) { - _enableAdapters(domain, _adapters); - initSettings(domain, _adapters, _settings); + _enableAdapters(domain, adapters); + initSettings(domain, adapters, settings); } /// @inheritdoc IGiriGiriBashi - function declareNoConfidence(uint256 domain, uint256 id, IAdapter[] memory _adapters) public { - checkAdapterOrderAndValidity(domain, _adapters); + function declareNoConfidence(uint256 domain, uint256 id, IAdapter[] memory adapters) public { + checkAdapterOrderAndValidity(domain, adapters); (uint256 threshold, uint256 count) = getThresholdAndCount(domain); - // check that there are enough adapters to prove no confidence - uint256 confidence = (count - _adapters.length) + 1; - if (confidence >= threshold) revert CannotProveNoConfidence(domain, id, _adapters); + if (adapters.length != count) revert CannotProveNoConfidence(domain, id, adapters); - bytes32[] memory hashes = new bytes32[](_adapters.length); - for (uint i = 0; i < _adapters.length; i++) hashes[i] = _adapters[i].getHash(domain, id); + bytes32[] memory hashes = new bytes32[](adapters.length); + uint256 zeroHashes = 0; + for (uint256 i = 0; i < adapters.length; i++) { + hashes[i] = adapters[i].getHash(domain, id); + if (hashes[i] == bytes32(0)) zeroHashes++; + if (zeroHashes == threshold) revert CannotProveNoConfidence(domain, id, adapters); + } - // prove that each member of _adapters disagrees - for (uint i = 0; i < hashes.length; i++) - for (uint j = 0; j < hashes.length; j++) - if (hashes[i] == hashes[j] && i != j) revert AdaptersAgreed(_adapters[i], _adapters[j]); + for (uint256 i = 0; i < hashes.length; i++) { + uint256 equalHashes = 1; + for (uint256 j = 0; j < hashes.length; j++) + if (hashes[i] == hashes[j] && i != j) { + equalHashes++; + if (equalHashes == threshold) { + revert AdaptersAgreed(); + } + } + } - domains[domain].threshold = type(uint256).max; - delete challengeRanges[domain]; + _setDomainThreshold(domain, type(uint256).max); + delete _challengeRanges[domain]; emit NoConfidenceDeclared(domain); } /// @inheritdoc IGiriGiriBashi - function disableAdapters(uint256 domain, IAdapter[] memory _adapters) public noConfidence(domain) { - _disableAdapters(domain, _adapters); - if (domains[domain].count == 0) domains[domain].threshold = 0; + function disableAdapters(uint256 domain, IAdapter[] memory adapters) public noConfidence(domain) { + _disableAdapters(domain, adapters); + if (getDomain(domain).count == 0) _setDomainThreshold(domain, 0); + } + + /// @inheritdoc IGiriGiriBashi + function getSettings(uint256 domain, IAdapter adapter) external view returns (Settings memory) { + return _settings[domain][adapter]; + } + + /// @inheritdoc IGiriGiriBashi + function getChallenge(bytes32 challengeId) external view returns (Challenge memory) { + return _challenges[challengeId]; } /// @inheritdoc IGiriGiriBashi @@ -101,6 +122,16 @@ contract GiriGiriBashi is IGiriGiriBashi, ShuSo { challengeId = keccak256(abi.encodePacked(domain, id, adapter)); } + /// @inheritdoc IGiriGiriBashi + function getChallengeRange(uint256 domain) external view returns (uint256) { + return _challengeRanges[domain]; + } + + /// @inheritdoc IGiriGiriBashi + function getHead(uint256 domain) external view returns (uint256) { + return _heads[domain]; + } + /// @inheritdoc IGiriGiriBashi function getThresholdHash(uint256 domain, uint256 id) public returns (bytes32 hash) { hash = _getThresholdHash(domain, id); @@ -114,8 +145,8 @@ contract GiriGiriBashi is IGiriGiriBashi, ShuSo { } /// @inheritdoc IGiriGiriBashi - function getHash(uint256 domain, uint256 id, IAdapter[] memory _adapters) public returns (bytes32 hash) { - hash = _getHash(domain, id, _adapters); + function getHash(uint256 domain, uint256 id, IAdapter[] memory adapters) public returns (bytes32 hash) { + hash = _getHash(domain, id, adapters); updateHead(domain, id); } @@ -124,16 +155,16 @@ contract GiriGiriBashi is IGiriGiriBashi, ShuSo { uint256 domain, IAdapter[] memory currentAdapters, IAdapter[] memory newAdapters, - Settings[] memory _settings + Settings[] memory settings ) public onlyOwner { - if (currentAdapters.length != newAdapters.length || currentAdapters.length != _settings.length) + if (currentAdapters.length != newAdapters.length || currentAdapters.length != settings.length) revert UnequalArrayLengths(); - for (uint i = 0; i < currentAdapters.length; i++) { - if (!settings[currentAdapters[i]].quarantined) revert AdapterNotQuarantined(currentAdapters[i]); + for (uint256 i = 0; i < currentAdapters.length; i++) { + if (!_settings[domain][currentAdapters[i]].quarantined) revert AdapterNotQuarantined(currentAdapters[i]); } _disableAdapters(domain, currentAdapters); _enableAdapters(domain, newAdapters); - initSettings(domain, newAdapters, _settings); + initSettings(domain, newAdapters, settings); } /// @inheritdoc IGiriGiriBashi @@ -141,46 +172,49 @@ contract GiriGiriBashi is IGiriGiriBashi, ShuSo { uint256 domain, uint256 id, IAdapter adapter, - IAdapter[] memory _adapters + IAdapter[] memory adapters ) public returns (bool success) { // check if challenge exists, revert if false bytes32 challengeId = getChallengeId(domain, id, adapter); - if (challenges[challengeId].challenger == address(0)) + if (_challenges[challengeId].challenger == address(0)) revert ChallengeNotFound(challengeId, domain, id, adapter); - Challenge storage challenge = challenges[challengeId]; - Settings storage adapterSettings = settings[adapter]; + for (uint256 i = 0; i < adapters.length; ) { + if (adapters[i] == adapter) revert AdaptersCannotContainChallengedAdapter(adapters, adapter); + unchecked { + ++i; + } + } + + Challenge storage challenge = _challenges[challengeId]; + Settings storage adapterSettings = _settings[domain][adapter]; bytes32 storedHash = adapter.getHash(domain, id); if (storedHash == bytes32(0)) { - // check block.timestamp is greater than challenge.timestamp + adapterSettings.timeout, revert if false. if (block.timestamp < challenge.timestamp + adapterSettings.timeout) revert AdapterHasNotYetTimedOut(adapter); adapterSettings.quarantined = true; - // send bond to challenger challenge.challenger.transfer(challenge.bond); success = true; } else { - // if _adapters + 1 equals threshold && _adapters + adapter report the same header - if (_adapters.length + 1 == domains[domain].threshold) { - bytes32 canonicalHash = hashi.getHash(domain, id, _adapters); + // if adapters + 1 equals threshold && adapters + adapter report the same header + if (adapters.length == getDomain(domain).threshold - 1) { + checkAdapterOrderAndValidity(domain, adapters); + bytes32 canonicalHash = hashi.getHash(domain, id, adapters); if (canonicalHash == storedHash) { - // return bond to recipient bondRecipient.transfer(challenge.bond); success = false; } else { - revert IHashi.AdaptersDisagree(adapter, _adapters[0]); + revert IHashi.AdaptersDisagree(adapter, adapters[0]); } } else { - // check if _adapters report the same header as adapter - bytes32 canonicalHash = getHash(domain, id, _adapters); + // check if adapters report the same header as adapter + bytes32 canonicalHash = getHash(domain, id, adapters); if (canonicalHash == storedHash) { bondRecipient.transfer(challenge.bond); success = false; } else { - // quaratine adapter adapterSettings.quarantined = true; - // return bond to challenger challenge.challenger.transfer(challenge.bond); success = true; } @@ -201,8 +235,8 @@ contract GiriGiriBashi is IGiriGiriBashi, ShuSo { /// @inheritdoc IGiriGiriBashi function setChallengeRange(uint256 domain, uint256 range) public onlyOwner { - if (challengeRanges[domain] != 0) revert ChallengeRangeAlreadySet(domain); - challengeRanges[domain] = range; + if (_challengeRanges[domain] != 0) revert ChallengeRangeAlreadySet(domain); + _challengeRanges[domain] = range; emit ChallengeRangeUpdated(domain, range); } @@ -215,21 +249,21 @@ contract GiriGiriBashi is IGiriGiriBashi, ShuSo { _setThreshold(domain, threshold); } - function initSettings(uint256 domain, IAdapter[] memory _adapters, Settings[] memory _settings) private { - if (_adapters.length != _settings.length) revert UnequalArrayLengths(); - for (uint i = 0; i < _adapters.length; i++) { + function initSettings(uint256 domain, IAdapter[] memory _adapters, Settings[] memory adapters) private { + if (_adapters.length != adapters.length) revert UnequalArrayLengths(); + for (uint256 i = 0; i < _adapters.length; i++) { IAdapter adapter = _adapters[i]; - settings[adapter].quarantined = false; - settings[adapter].minimumBond = _settings[i].minimumBond; - settings[adapter].startId = _settings[i].startId; - settings[adapter].idDepth = _settings[i].idDepth; - settings[adapter].timeout = _settings[i].timeout; - emit SettingsInitialized(domain, adapter, _settings[i]); + _settings[domain][adapter].quarantined = false; + _settings[domain][adapter].minimumBond = adapters[i].minimumBond; + _settings[domain][adapter].startId = adapters[i].startId; + _settings[domain][adapter].idDepth = adapters[i].idDepth; + _settings[domain][adapter].timeout = adapters[i].timeout; + emit SettingsInitialized(domain, adapter, adapters[i]); } } function updateHead(uint256 domain, uint256 id) private { - if (id > heads[domain]) heads[domain] = id; + if (id > _heads[domain]) _heads[domain] = id; emit NewHead(domain, id); } } diff --git a/packages/evm/contracts/ownable/ShoyuBashi.sol b/packages/evm/contracts/ownable/ShoyuBashi.sol index ee3e7837..7a6c5ae0 100644 --- a/packages/evm/contracts/ownable/ShoyuBashi.sol +++ b/packages/evm/contracts/ownable/ShoyuBashi.sol @@ -19,13 +19,13 @@ contract ShoyuBashi is IShoyuBashi, ShuSo { } /// @inheritdoc IShoyuBashi - function enableAdapters(uint256 domain, IAdapter[] memory _adapters) public { - _enableAdapters(domain, _adapters); + function enableAdapters(uint256 domain, IAdapter[] memory adapters) public { + _enableAdapters(domain, adapters); } /// @inheritdoc IShoyuBashi - function disableAdapters(uint256 domain, IAdapter[] memory _adapters) public { - _disableAdapters(domain, _adapters); + function disableAdapters(uint256 domain, IAdapter[] memory adapters) public { + _disableAdapters(domain, adapters); } /// @inheritdoc IShoyuBashi @@ -39,7 +39,7 @@ contract ShoyuBashi is IShoyuBashi, ShuSo { } /// @inheritdoc IShoyuBashi - function getHash(uint256 domain, uint256 id, IAdapter[] memory _adapters) public view returns (bytes32) { - return _getHash(domain, id, _adapters); + function getHash(uint256 domain, uint256 id, IAdapter[] memory adapters) public view returns (bytes32) { + return _getHash(domain, id, adapters); } } diff --git a/packages/evm/contracts/ownable/ShuSo.sol b/packages/evm/contracts/ownable/ShuSo.sol index 1d522532..da067e93 100644 --- a/packages/evm/contracts/ownable/ShuSo.sol +++ b/packages/evm/contracts/ownable/ShuSo.sol @@ -10,8 +10,8 @@ abstract contract ShuSo is IShuSho, OwnableUpgradeable { IAdapter internal constant LIST_END = IAdapter(address(0x1)); IHashi public hashi; - mapping(uint256 => mapping(IAdapter => Link)) public adapters; - mapping(uint256 => Domain) public domains; + mapping(uint256 => mapping(IAdapter => Link)) private _adapters; + mapping(uint256 => Domain) private _domains; constructor(address _owner, address _hashi) { bytes memory initParams = abi.encode(_owner, _hashi); @@ -27,28 +27,38 @@ abstract contract ShuSo is IShuSho, OwnableUpgradeable { } /// @inheritdoc IShuSho - function checkAdapterOrderAndValidity(uint256 domain, IAdapter[] memory _adapters) public view { - for (uint256 i = 0; i < _adapters.length; i++) { - IAdapter adapter = _adapters[i]; - if (i > 0 && adapter <= _adapters[i - 1]) revert DuplicateOrOutOfOrderAdapters(adapter, _adapters[i - 1]); - if (adapters[domain][adapter].next == IAdapter(address(0))) revert InvalidAdapter(adapter); + function checkAdapterOrderAndValidity(uint256 domain, IAdapter[] memory adapters) public view { + for (uint256 i = 0; i < adapters.length; i++) { + IAdapter adapter = adapters[i]; + if (i > 0 && adapter <= adapters[i - 1]) revert DuplicateOrOutOfOrderAdapters(adapter, adapters[i - 1]); + if (_adapters[domain][adapter].next == IAdapter(address(0))) revert InvalidAdapter(adapter); } } + /// @inheritdoc IShuSho + function getAdapterLink(uint256 domain, IAdapter adapter) public view returns (Link memory) { + return _adapters[domain][adapter]; + } + /// @inheritdoc IShuSho function getAdapters(uint256 domain) public view returns (IAdapter[] memory) { - IAdapter[] memory _adapters = new IAdapter[](domains[domain].count); - IAdapter currentAdapter = adapters[domain][LIST_END].next; - for (uint256 i = 0; i < _adapters.length; i++) { - _adapters[i] = currentAdapter; - currentAdapter = adapters[domain][currentAdapter].next; + IAdapter[] memory adapters = new IAdapter[](_domains[domain].count); + IAdapter currentAdapter = _adapters[domain][LIST_END].next; + for (uint256 i = 0; i < adapters.length; i++) { + adapters[i] = currentAdapter; + currentAdapter = _adapters[domain][currentAdapter].next; } - return _adapters; + return adapters; + } + + /// @inheritdoc IShuSho + function getDomain(uint256 domain) public view returns (Domain memory) { + return _domains[domain]; } /// @inheritdoc IShuSho function getThresholdAndCount(uint256 domain_) public view returns (uint256, uint256) { - Domain storage domain = domains[domain_]; + Domain storage domain = _domains[domain_]; uint256 threshold = domain.threshold; uint256 count = domain.count; if (threshold == 0) threshold = count; @@ -60,75 +70,75 @@ abstract contract ShuSo is IShuSho, OwnableUpgradeable { /** * @dev Disables the given adapters for a given domain. * @param domain - Uint256 identifier for the domain for which to set adapters. - * @param _adapters - Array of adapter addresses. - * @notice Reverts if _adapters are out of order or contain duplicates. + * @param adapters - Array of adapter addresses. + * @notice Reverts if adapters are out of order or contain duplicates. * @notice Only callable by the owner of this contract. */ - function _disableAdapters(uint256 domain, IAdapter[] memory _adapters) internal onlyOwner { - if (domains[domain].count == 0) revert NoAdaptersEnabled(domain); - if (_adapters.length == 0) revert NoAdaptersGiven(); - for (uint256 i = 0; i < _adapters.length; i++) { - IAdapter adapter = _adapters[i]; + function _disableAdapters(uint256 domain, IAdapter[] memory adapters) internal onlyOwner { + if (_domains[domain].count == 0) revert NoAdaptersEnabled(domain); + if (adapters.length == 0) revert NoAdaptersGiven(); + for (uint256 i = 0; i < adapters.length; i++) { + IAdapter adapter = adapters[i]; if (adapter == IAdapter(address(0)) || adapter == LIST_END) revert InvalidAdapter(adapter); - Link memory current = adapters[domain][adapter]; + Link memory current = _adapters[domain][adapter]; if (current.next == IAdapter(address(0))) revert AdapterNotEnabled(adapter); IAdapter next = current.next; IAdapter previous = current.previous; - adapters[domain][next].previous = previous; - adapters[domain][previous].next = next; - delete adapters[domain][adapter].next; - delete adapters[domain][adapter].previous; - domains[domain].count--; + _adapters[domain][next].previous = previous; + _adapters[domain][previous].next = next; + delete _adapters[domain][adapter].next; + delete _adapters[domain][adapter].previous; + _domains[domain].count--; } - emit AdaptersDisabled(domain, _adapters); + emit AdaptersDisabled(domain, adapters); } /** * @dev Enables the given adapters for a given domain. * @param domain - Uint256 identifier for the domain for which to set adapters. - * @param _adapters - Array of adapter addresses. - * @notice Reverts if _adapters are out of order or contain duplicates. + * @param adapters - Array of adapter addresses. + * @notice Reverts if adapters are out of order or contain duplicates. * @notice Only callable by the owner of this contract. */ - function _enableAdapters(uint256 domain, IAdapter[] memory _adapters) internal onlyOwner { - if (adapters[domain][LIST_END].next == IAdapter(address(0))) { - adapters[domain][LIST_END].next = LIST_END; - adapters[domain][LIST_END].previous = LIST_END; + function _enableAdapters(uint256 domain, IAdapter[] memory adapters) internal onlyOwner { + if (_adapters[domain][LIST_END].next == IAdapter(address(0))) { + _adapters[domain][LIST_END].next = LIST_END; + _adapters[domain][LIST_END].previous = LIST_END; } - if (_adapters.length == 0) revert NoAdaptersGiven(); - for (uint256 i = 0; i < _adapters.length; i++) { - IAdapter adapter = _adapters[i]; + if (adapters.length == 0) revert NoAdaptersGiven(); + for (uint256 i = 0; i < adapters.length; i++) { + IAdapter adapter = adapters[i]; if (adapter == IAdapter(address(0)) || adapter == LIST_END) revert InvalidAdapter(adapter); - if (adapters[domain][adapter].next != IAdapter(address(0))) revert AdapterAlreadyEnabled(adapter); - IAdapter previous = adapters[domain][LIST_END].previous; - adapters[domain][previous].next = adapter; - adapters[domain][adapter].previous = previous; - adapters[domain][LIST_END].previous = adapter; - adapters[domain][adapter].next = LIST_END; - domains[domain].count++; + if (_adapters[domain][adapter].next != IAdapter(address(0))) revert AdapterAlreadyEnabled(adapter); + IAdapter previous = _adapters[domain][LIST_END].previous; + _adapters[domain][previous].next = adapter; + _adapters[domain][adapter].previous = previous; + _adapters[domain][LIST_END].previous = adapter; + _adapters[domain][adapter].next = LIST_END; + _domains[domain].count++; } - emit AdaptersEnabled(domain, _adapters); + emit AdaptersEnabled(domain, adapters); } /** * @dev Returns the hash unanimously agreed upon by all of the given adapters. * @param domain - Uint256 identifier for the domain to query. * @param id - Uint256 identifier to query. - * @param _adapters - Array of adapter addresses to query. + * @param adapters - Array of adapter addresses to query. * @return hash - Bytes32 hash agreed upon by the adapters for the given domain. - * @notice _adapters must be in numerical order from smallest to largest and contain no duplicates. - * @notice Reverts if _adapters are out of order or contain duplicates. + * @notice adapters must be in numerical order from smallest to largest and contain no duplicates. + * @notice Reverts if adapters are out of order or contain duplicates. * @notice Reverts if adapters disagree. * @notice Revert if the adapters do not yet have the hash for the given ID. * @notice Reverts if no adapters are set for the given domain. */ - function _getHash(uint256 domain, uint256 id, IAdapter[] memory _adapters) internal view returns (bytes32) { + function _getHash(uint256 domain, uint256 id, IAdapter[] memory adapters) internal view returns (bytes32) { (uint256 threshold, uint256 count) = getThresholdAndCount(domain); - if (_adapters.length == 0) revert NoAdaptersGiven(); + if (adapters.length == 0) revert NoAdaptersGiven(); if (count == 0) revert NoAdaptersEnabled(domain); - if (_adapters.length < threshold) revert ThresholdNotMet(); - checkAdapterOrderAndValidity(domain, _adapters); - return hashi.getHash(domain, id, _adapters); + if (adapters.length < threshold) revert ThresholdNotMet(); + checkAdapterOrderAndValidity(domain, adapters); + return hashi.getHash(domain, id, adapters); } /** @@ -141,26 +151,26 @@ abstract contract ShuSo is IShuSho, OwnableUpgradeable { * @notice Reverts if no adapters are set for the given domain. */ function _getThresholdHash(uint256 domain, uint256 id) internal view returns (bytes32 hash) { - IAdapter[] memory _adapters = getAdapters(domain); + IAdapter[] memory adapters = getAdapters(domain); (uint256 threshold, uint256 count) = getThresholdAndCount(domain); if (count == 0) revert NoAdaptersEnabled(domain); - if (_adapters.length < threshold) revert ThresholdNotMet(); + if (adapters.length < threshold) revert ThresholdNotMet(); - bytes32[] memory hashes = new bytes32[](_adapters.length); - for (uint i = 0; i < _adapters.length; i++) { - try _adapters[i].getHash(domain, id) returns (bytes32 currentHash) { + bytes32[] memory hashes = new bytes32[](adapters.length); + for (uint256 i = 0; i < adapters.length; i++) { + try adapters[i].getHash(domain, id) returns (bytes32 currentHash) { hashes[i] = currentHash; } catch {} // solhint-disable no-empty-blocks } - for (uint i = 0; i < hashes.length; i++) { + for (uint256 i = 0; i < hashes.length; i++) { if (i > hashes.length - threshold) break; bytes32 baseHash = hashes[i]; if (baseHash == bytes32(0)) continue; uint256 num = 0; - for (uint j = i; j < hashes.length; j++) { + for (uint256 j = i; j < hashes.length; j++) { if (baseHash == hashes[j]) { num++; if (num == threshold) return hashes[i]; @@ -180,11 +190,11 @@ abstract contract ShuSo is IShuSho, OwnableUpgradeable { * @notice Reverts if no adapters are set for the given domain. */ function _getUnanimousHash(uint256 domain, uint256 id) internal view returns (bytes32 hash) { - IAdapter[] memory _adapters = getAdapters(domain); + IAdapter[] memory adapters = getAdapters(domain); (uint256 threshold, uint256 count) = getThresholdAndCount(domain); if (count == 0) revert NoAdaptersEnabled(domain); - if (_adapters.length < threshold) revert ThresholdNotMet(); - return hashi.getHash(domain, id, _adapters); + if (adapters.length < threshold) revert ThresholdNotMet(); + return hashi.getHash(domain, id, adapters); } /** @@ -206,8 +216,15 @@ abstract contract ShuSo is IShuSho, OwnableUpgradeable { * @notice Reverts if threshold is already set to the given value. */ function _setThreshold(uint256 domain, uint256 threshold) internal onlyOwner { - if (domains[domain].threshold == threshold) revert DuplicateThreashold(threshold); - domains[domain].threshold = threshold; + uint256 count = _domains[domain].count; + if (count == 0) revert CountCannotBeZero(); + if (threshold < (count / 2) + 1) revert InvalidThreshold(threshold); + if (_domains[domain].threshold == threshold) revert DuplicateThreashold(threshold); + _domains[domain].threshold = threshold; emit ThresholdSet(domain, threshold); } + + function _setDomainThreshold(uint256 domainId, uint256 threshold) internal { + _domains[domainId].threshold = threshold; + } } diff --git a/packages/evm/test/02_ShoyuBashi.spec.ts b/packages/evm/test/02_ShoyuBashi.spec.ts index af46d28f..747fb034 100644 --- a/packages/evm/test/02_ShoyuBashi.spec.ts +++ b/packages/evm/test/02_ShoyuBashi.spec.ts @@ -22,7 +22,6 @@ const setup = async () => { await mockAdapter.setHashes(DOMAIN_ID, [0, 1, 2], [HASH_ZERO, HASH_GOOD, HASH_GOOD]) await anotherAdapter.setHashes(DOMAIN_ID, [0, 1, 2], [HASH_ZERO, HASH_GOOD, HASH_BAD]) - await shoyuBashi.setThreshold(DOMAIN_ID, 2) return { wallet, @@ -81,6 +80,8 @@ describe("ShoyuBashi", function () { }) it("Reverts if threshold is already set", async function () { const { shoyuBashi } = await setup() + await shoyuBashi.enableAdapters(DOMAIN_ID, [ADDRESS_TWO, ADDRESS_THREE]) + await shoyuBashi.setThreshold(DOMAIN_ID, 2) await expect(shoyuBashi.setThreshold(DOMAIN_ID, 2)).to.be.revertedWithCustomError( shoyuBashi, "DuplicateThreashold", @@ -88,12 +89,14 @@ describe("ShoyuBashi", function () { }) it("Sets threshold for the given ChainID", async function () { const { shoyuBashi } = await setup() - expect(await shoyuBashi.setThreshold(DOMAIN_ID, 3)) - expect((await shoyuBashi.domains(DOMAIN_ID)).threshold).to.equal(3) + await shoyuBashi.enableAdapters(DOMAIN_ID, [ADDRESS_TWO, ADDRESS_THREE]) + expect(await shoyuBashi.setThreshold(DOMAIN_ID, 2)) + expect((await shoyuBashi.getDomain(DOMAIN_ID)).threshold).to.equal(2) }) it("Emits HashiSet() event", async function () { const { shoyuBashi } = await setup() - await expect(shoyuBashi.setThreshold(DOMAIN_ID, 3)).to.emit(shoyuBashi, "ThresholdSet").withArgs(DOMAIN_ID, 3) + await shoyuBashi.enableAdapters(DOMAIN_ID, [ADDRESS_TWO, ADDRESS_THREE]) + await expect(shoyuBashi.setThreshold(DOMAIN_ID, 2)).to.emit(shoyuBashi, "ThresholdSet").withArgs(DOMAIN_ID, 2) }) }) @@ -140,12 +143,12 @@ describe("ShoyuBashi", function () { const adapters = await shoyuBashi.getAdapters(DOMAIN_ID) await expect(adapters[0]).to.equal(ADDRESS_TWO) await expect(adapters[1]).to.equal(ADDRESS_THREE) - expect((await shoyuBashi.adapters(DOMAIN_ID, LIST_END)).next).to.equal(ADDRESS_TWO) - expect((await shoyuBashi.adapters(DOMAIN_ID, LIST_END)).previous).to.equal(ADDRESS_THREE) - expect((await shoyuBashi.adapters(DOMAIN_ID, ADDRESS_TWO)).next).to.equal(ADDRESS_THREE) - expect((await shoyuBashi.adapters(DOMAIN_ID, ADDRESS_TWO)).previous).to.equal(LIST_END) - expect((await shoyuBashi.adapters(DOMAIN_ID, ADDRESS_THREE)).next).to.equal(LIST_END) - expect((await shoyuBashi.adapters(DOMAIN_ID, ADDRESS_THREE)).previous).to.equal(ADDRESS_TWO) + expect((await shoyuBashi.getAdapterLink(DOMAIN_ID, LIST_END)).next).to.equal(ADDRESS_TWO) + expect((await shoyuBashi.getAdapterLink(DOMAIN_ID, LIST_END)).previous).to.equal(ADDRESS_THREE) + expect((await shoyuBashi.getAdapterLink(DOMAIN_ID, ADDRESS_TWO)).next).to.equal(ADDRESS_THREE) + expect((await shoyuBashi.getAdapterLink(DOMAIN_ID, ADDRESS_TWO)).previous).to.equal(LIST_END) + expect((await shoyuBashi.getAdapterLink(DOMAIN_ID, ADDRESS_THREE)).next).to.equal(LIST_END) + expect((await shoyuBashi.getAdapterLink(DOMAIN_ID, ADDRESS_THREE)).previous).to.equal(ADDRESS_TWO) }) it("Emits AdaptersEnabled() event", async function () { const { shoyuBashi } = await setup() @@ -246,9 +249,9 @@ describe("ShoyuBashi", function () { it("Returns threshold and count", async function () { const { shoyuBashi } = await setup() await shoyuBashi.enableAdapters(DOMAIN_ID, [ADDRESS_TWO, ADDRESS_THREE]) - await shoyuBashi.setThreshold(DOMAIN_ID, 1) + await shoyuBashi.setThreshold(DOMAIN_ID, 2) const [threshold] = await shoyuBashi.getThresholdAndCount(DOMAIN_ID) - await expect(threshold).to.equal(1) + await expect(threshold).to.equal(2) }) }) @@ -263,6 +266,7 @@ describe("ShoyuBashi", function () { it("Reverts if threshold is not met", async function () { const { shoyuBashi, mockAdapter } = await setup() await shoyuBashi.enableAdapters(DOMAIN_ID, [mockAdapter.address]) + await shoyuBashi.setThreshold(DOMAIN_ID, 2) await expect(shoyuBashi.getUnanimousHash(DOMAIN_ID, 1)).to.be.revertedWithCustomError( shoyuBashi, "ThresholdNotMet", @@ -286,6 +290,7 @@ describe("ShoyuBashi", function () { it("Reverts if threshold is not met", async function () { const { shoyuBashi, mockAdapter, anotherAdapter } = await setup() await shoyuBashi.enableAdapters(DOMAIN_ID, [mockAdapter.address, anotherAdapter.address]) + await shoyuBashi.setThreshold(DOMAIN_ID, 3) await expect(shoyuBashi.getThresholdHash(DOMAIN_ID, 2)).to.be.revertedWithCustomError( shoyuBashi, "ThresholdNotMet", @@ -310,6 +315,7 @@ describe("ShoyuBashi", function () { it("Reverts if threshold is not met", async function () { const { shoyuBashi, mockAdapter } = await setup() await shoyuBashi.enableAdapters(DOMAIN_ID, [mockAdapter.address]) + await shoyuBashi.setThreshold(DOMAIN_ID, 2) await expect(shoyuBashi.getHash(DOMAIN_ID, 1, [mockAdapter.address])).to.be.revertedWithCustomError( shoyuBashi, "ThresholdNotMet", diff --git a/packages/evm/test/03_GiriGiriBashi.spec.ts b/packages/evm/test/03_GiriGiriBashi.spec.ts index 5b58c055..df378b2c 100644 --- a/packages/evm/test/03_GiriGiriBashi.spec.ts +++ b/packages/evm/test/03_GiriGiriBashi.spec.ts @@ -38,18 +38,22 @@ const setup = async (_configs?: any) => { const secondMockAdapter = await MockAdapter.deploy() const thirdMockAdapter = await MockAdapter.deploy() - await mockAdapter.setHashes(DOMAIN_ID, [0, 1, 20, 21, 22], [HASH_ZERO, HASH_GOOD, HASH_BAD, HASH_GOOD, HASH_BAD]) + await mockAdapter.setHashes( + DOMAIN_ID, + [0, 1, 20, 21, 22, 23], + [HASH_ZERO, HASH_GOOD, HASH_BAD, HASH_GOOD, HASH_BAD, HASH_ZERO], + ) await secondMockAdapter.setHashes( DOMAIN_ID, - [0, 1, 20, 21, 22], - [HASH_ZERO, HASH_GOOD, HASH_GOOD, HASH_GOOD, HASH_GOOD], + [0, 1, 20, 21, 22, 23], + [HASH_ZERO, HASH_GOOD, HASH_GOOD, HASH_GOOD, HASH_GOOD, HASH_ZERO], ) await thirdMockAdapter.setHashes( DOMAIN_ID, - [0, 1, 20, 21, 22], - [HASH_ZERO, HASH_GOOD, HASH_DEAD, HASH_GOOD, HASH_GOOD], + [0, 1, 20, 21, 22, 23], + [HASH_ZERO, HASH_GOOD, HASH_DEAD, HASH_GOOD, HASH_GOOD, HASH_GOOD], ) - await giriGiriBashi.setThreshold(DOMAIN_ID, _configs?.threshold || 2) + await giriGiriBashi.setChallengeRange(DOMAIN_ID, CHALLENGE_RANGE) const settings = { @@ -111,21 +115,50 @@ describe("GiriGiriBashi", function () { it("Reverts if count is greater than zero", async function () { const { giriGiriBashi, mockAdapter, settings } = await setup() await giriGiriBashi.enableAdapters(DOMAIN_ID, [mockAdapter.address], [settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) await expect(giriGiriBashi.setThreshold(DOMAIN_ID, 2)).to.be.revertedWithCustomError( giriGiriBashi, "CountMustBeZero", ) }) - it("Sets threshold for the given ChainID", async function () { + it("Reverts if adapters are not enabled", async function () { const { giriGiriBashi } = await setup() - expect(await giriGiriBashi.setThreshold(DOMAIN_ID, 3)) - expect((await giriGiriBashi.domains(DOMAIN_ID)).threshold).to.equal(3) + await expect(giriGiriBashi.setThreshold(DOMAIN_ID, 2)).to.be.revertedWithCustomError( + giriGiriBashi, + "CountCannotBeZero", + ) + }) + it("Reverts if the threshold is less than them majority of adapters", async function () { + const { giriGiriBashi, settings, mockAdapter, secondMockAdapter, thirdMockAdapter } = await setup() + await giriGiriBashi.enableAdapters( + DOMAIN_ID, + [mockAdapter.address, secondMockAdapter.address, thirdMockAdapter.address], + [settings, settings, settings], + ) + await expect(giriGiriBashi.setThreshold(DOMAIN_ID, 1)) + .to.be.revertedWithCustomError(giriGiriBashi, "InvalidThreshold") + .withArgs(1) + }) + it("Sets threshold for the given ChainID", async function () { + const { giriGiriBashi, mockAdapter, secondMockAdapter, settings } = await setup() + await giriGiriBashi.enableAdapters( + DOMAIN_ID, + [mockAdapter.address, secondMockAdapter.address], + [settings, settings], + ) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) + expect((await giriGiriBashi.getDomain(DOMAIN_ID)).threshold).to.equal(2) }) it("Emits HashiSet() event", async function () { - const { giriGiriBashi } = await setup() - await expect(giriGiriBashi.setThreshold(DOMAIN_ID, 3)) + const { giriGiriBashi, mockAdapter, secondMockAdapter, settings } = await setup() + await giriGiriBashi.enableAdapters( + DOMAIN_ID, + [mockAdapter.address, secondMockAdapter.address], + [settings, settings], + ) + await expect(giriGiriBashi.setThreshold(DOMAIN_ID, 2)) .to.emit(giriGiriBashi, "ThresholdSet") - .withArgs(DOMAIN_ID, 3) + .withArgs(DOMAIN_ID, 2) }) }) @@ -139,7 +172,8 @@ describe("GiriGiriBashi", function () { }) it("Reverts if any adapters are already enabled", async function () { const { giriGiriBashi, settings } = await setup() - await expect(giriGiriBashi.enableAdapters(DOMAIN_ID, [ADDRESS_TWO], [settings])) + await giriGiriBashi.enableAdapters(DOMAIN_ID, [ADDRESS_TWO], [settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 1) await expect(giriGiriBashi.enableAdapters(DOMAIN_ID, [ADDRESS_TWO], [settings])).to.be.revertedWithCustomError( giriGiriBashi, "CountMustBeZero", @@ -153,23 +187,24 @@ describe("GiriGiriBashi", function () { }) it("Enables the given adapters", async function () { const { giriGiriBashi, settings } = await setup() - await expect(giriGiriBashi.enableAdapters(DOMAIN_ID, [ADDRESS_TWO, ADDRESS_THREE], [settings, settings])) + await giriGiriBashi.enableAdapters(DOMAIN_ID, [ADDRESS_TWO, ADDRESS_THREE], [settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) const adapters = await giriGiriBashi.getAdapters(DOMAIN_ID) await expect(adapters[0]).to.equal(ADDRESS_TWO) await expect(adapters[1]).to.equal(ADDRESS_THREE) - expect((await giriGiriBashi.adapters(DOMAIN_ID, LIST_END)).next).to.equal(ADDRESS_TWO) - expect((await giriGiriBashi.adapters(DOMAIN_ID, LIST_END)).previous).to.equal(ADDRESS_THREE) - expect((await giriGiriBashi.adapters(DOMAIN_ID, ADDRESS_TWO)).next).to.equal(ADDRESS_THREE) - expect((await giriGiriBashi.adapters(DOMAIN_ID, ADDRESS_TWO)).previous).to.equal(LIST_END) - expect((await giriGiriBashi.adapters(DOMAIN_ID, ADDRESS_THREE)).next).to.equal(LIST_END) - expect((await giriGiriBashi.adapters(DOMAIN_ID, ADDRESS_THREE)).previous).to.equal(ADDRESS_TWO) - let adapterSettings = await giriGiriBashi.settings(ADDRESS_TWO) + expect((await giriGiriBashi.getAdapterLink(DOMAIN_ID, LIST_END)).next).to.equal(ADDRESS_TWO) + expect((await giriGiriBashi.getAdapterLink(DOMAIN_ID, LIST_END)).previous).to.equal(ADDRESS_THREE) + expect((await giriGiriBashi.getAdapterLink(DOMAIN_ID, ADDRESS_TWO)).next).to.equal(ADDRESS_THREE) + expect((await giriGiriBashi.getAdapterLink(DOMAIN_ID, ADDRESS_TWO)).previous).to.equal(LIST_END) + expect((await giriGiriBashi.getAdapterLink(DOMAIN_ID, ADDRESS_THREE)).next).to.equal(LIST_END) + expect((await giriGiriBashi.getAdapterLink(DOMAIN_ID, ADDRESS_THREE)).previous).to.equal(ADDRESS_TWO) + let adapterSettings = await giriGiriBashi.getSettings(DOMAIN_ID, ADDRESS_TWO) expect(adapterSettings.quarantined).to.deep.equal(settings.quarantined) expect(adapterSettings.minimumBond).to.deep.equal(settings.minimumBond) expect(adapterSettings.startId).to.deep.equal(settings.startId) expect(adapterSettings.idDepth).to.deep.equal(settings.idDepth) expect(adapterSettings.timeout).to.deep.equal(settings.timeout) - adapterSettings = await giriGiriBashi.settings(ADDRESS_THREE) + adapterSettings = await giriGiriBashi.getSettings(DOMAIN_ID, ADDRESS_THREE) expect(adapterSettings.quarantined).to.deep.equal(settings.quarantined) expect(adapterSettings.minimumBond).to.deep.equal(settings.minimumBond) expect(adapterSettings.startId).to.deep.equal(settings.startId) @@ -194,8 +229,8 @@ describe("GiriGiriBashi", function () { }) it("Disables the given adapters", async function () { const { giriGiriBashi, settings } = await setup() - await giriGiriBashi.setThreshold(DOMAIN_ID, ethers.constants.MaxUint256) await giriGiriBashi.enableAdapters(DOMAIN_ID, [ADDRESS_TWO, ADDRESS_THREE], [settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, ethers.constants.MaxUint256) await giriGiriBashi.disableAdapters(DOMAIN_ID, [ADDRESS_TWO, ADDRESS_THREE]) const adapters = await giriGiriBashi.getAdapters(DOMAIN_ID) await expect(adapters[0]).to.equal(undefined) @@ -210,26 +245,26 @@ describe("GiriGiriBashi", function () { [mockAdapter.address, secondMockAdapter.address], [settings, settings], ) - const oldHead = await giriGiriBashi.heads(DOMAIN_ID) + const oldHead = await giriGiriBashi.getHead(DOMAIN_ID) await giriGiriBashi.getUnanimousHash(DOMAIN_ID, 1) - const newHead = await giriGiriBashi.heads(DOMAIN_ID) + const newHead = await giriGiriBashi.getHead(DOMAIN_ID) expect(newHead).not.to.equal(oldHead) }) }) describe("getThresholdHash()", function () { - for (let threshold = 1; threshold <= 3; threshold++) { + for (let threshold = 2; threshold <= 3; threshold++) { it(`Updates head for given domain with ${threshold}/3`, async function () { - const { giriGiriBashi, mockAdapter, secondMockAdapter, thirdMockAdapter, settings } = await setup({ threshold }) + const { giriGiriBashi, mockAdapter, secondMockAdapter, thirdMockAdapter, settings } = await setup() await giriGiriBashi.enableAdapters( DOMAIN_ID, [mockAdapter.address, secondMockAdapter.address, thirdMockAdapter.address], [settings, settings, settings], ) - const oldHead = await giriGiriBashi.heads(DOMAIN_ID) + const oldHead = await giriGiriBashi.getHead(DOMAIN_ID) expect(await giriGiriBashi.callStatic.getThresholdHash(DOMAIN_ID, 1)).to.equal(HASH_GOOD) await giriGiriBashi.getThresholdHash(DOMAIN_ID, 1) - const newHead = await giriGiriBashi.heads(DOMAIN_ID) + const newHead = await giriGiriBashi.getHead(DOMAIN_ID) expect(newHead).not.to.equal(oldHead) }) } @@ -243,15 +278,16 @@ describe("GiriGiriBashi", function () { [mockAdapter.address, secondMockAdapter.address], [settings, settings], ) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) let adapters if (secondMockAdapter.address > mockAdapter.address) { adapters = [mockAdapter.address, secondMockAdapter.address] } else { adapters = [secondMockAdapter.address, mockAdapter.address] } - const oldHead = await giriGiriBashi.heads(DOMAIN_ID) + const oldHead = await giriGiriBashi.getHead(DOMAIN_ID) await giriGiriBashi.getHash(DOMAIN_ID, 1, adapters) - const newHead = await giriGiriBashi.heads(DOMAIN_ID) + const newHead = await giriGiriBashi.getHead(DOMAIN_ID) expect(newHead).not.to.equal(oldHead) }) }) @@ -270,6 +306,7 @@ describe("GiriGiriBashi", function () { [mockAdapter.address, secondMockAdapter.address], [settings, settings], ) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) await expect(giriGiriBashi.challengeAdapter(DOMAIN_ID, 1, mockAdapter.address)) .to.be.revertedWithCustomError(giriGiriBashi, "NotEnoughValue") .withArgs(mockAdapter.address, 0) @@ -278,15 +315,16 @@ describe("GiriGiriBashi", function () { const { giriGiriBashi, mockAdapter, secondMockAdapter, settings } = await setup() const adapters = [mockAdapter.address, secondMockAdapter.address].sort(compareAddresses) await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) await giriGiriBashi.getHash(DOMAIN_ID, 21, adapters) - const head = await giriGiriBashi.heads(DOMAIN_ID) + const head = await giriGiriBashi.getHead(DOMAIN_ID) const challengeBlock = head - CHALLENGE_RANGE + 2 await giriGiriBashi.challengeAdapter(DOMAIN_ID, challengeBlock, mockAdapter.address, { value: BOND, }) const challengeId = await giriGiriBashi.getChallengeId(DOMAIN_ID, challengeBlock, mockAdapter.address) - const challenge = await giriGiriBashi.challenges(challengeId) + const challenge = await giriGiriBashi.getChallenge(challengeId) const increaseAmount = challenge.timestamp.add(settings.timeout).add(1) await network.provider.send("evm_setNextBlockTimestamp", [increaseAmount.toHexString()]) @@ -300,12 +338,57 @@ describe("GiriGiriBashi", function () { .to.be.revertedWithCustomError(giriGiriBashi, "AlreadyQuarantined") .withArgs(mockAdapter.address) }) + it("Reverts if adapters array contains duplicates", async function () { + const { giriGiriBashi, mockAdapter, secondMockAdapter, settings } = await setup() + const adapters = [mockAdapter.address, secondMockAdapter.address].sort(compareAddresses) + await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) + + await giriGiriBashi.getHash(DOMAIN_ID, 21, adapters) + const head = await giriGiriBashi.getHead(DOMAIN_ID) + const challengeBlock = head - CHALLENGE_RANGE + 2 + await giriGiriBashi.challengeAdapter(DOMAIN_ID, challengeBlock, mockAdapter.address, { + value: BOND, + }) + const challengeId = await giriGiriBashi.getChallengeId(DOMAIN_ID, challengeBlock, mockAdapter.address) + const challenge = await giriGiriBashi.getChallenge(challengeId) + const increaseAmount = challenge.timestamp.add(settings.timeout).add(1) + + await network.provider.send("evm_setNextBlockTimestamp", [increaseAmount.toHexString()]) + await mockAdapter.setHashes(DOMAIN_ID, [challengeBlock], [HASH_GOOD]) + await secondMockAdapter.setHashes(DOMAIN_ID, [challengeBlock], [HASH_GOOD]) + + await expect( + giriGiriBashi.resolveChallenge(DOMAIN_ID, challengeBlock, mockAdapter.address, [ + secondMockAdapter.address, + secondMockAdapter.address, + ]), + ).to.be.revertedWithCustomError(giriGiriBashi, "DuplicateOrOutOfOrderAdapters") + }) + it("Reverts if adapters array contains the challenged adapter", async function () { + const { giriGiriBashi, mockAdapter, secondMockAdapter, settings } = await setup() + const adapters = [mockAdapter.address, secondMockAdapter.address].sort(compareAddresses) + await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings]) + + await giriGiriBashi.getHash(DOMAIN_ID, 21, adapters) + const head = await giriGiriBashi.getHead(DOMAIN_ID) + const challengeBlock = head - CHALLENGE_RANGE + 2 + await giriGiriBashi.challengeAdapter(DOMAIN_ID, challengeBlock, mockAdapter.address, { + value: BOND, + }) + + const wrongAdapters = [secondMockAdapter.address, mockAdapter.address] + await expect(giriGiriBashi.resolveChallenge(DOMAIN_ID, challengeBlock, mockAdapter.address, wrongAdapters)) + .to.revertedWithCustomError(giriGiriBashi, "AdaptersCannotContainChallengedAdapter") + .withArgs(wrongAdapters, mockAdapter.address) + }) it("Reverts if duplicate challenge exists", async function () { const { giriGiriBashi, mockAdapter, secondMockAdapter, settings } = await setup() const adapters = [mockAdapter.address, secondMockAdapter.address].sort(compareAddresses) await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) await giriGiriBashi.getHash(DOMAIN_ID, 21, adapters) - const head = await giriGiriBashi.heads(DOMAIN_ID) + const head = await giriGiriBashi.getHead(DOMAIN_ID) expect( await giriGiriBashi.challengeAdapter(DOMAIN_ID, head - CHALLENGE_RANGE + 1, mockAdapter.address, { value: BOND, @@ -321,8 +404,9 @@ describe("GiriGiriBashi", function () { const { giriGiriBashi, mockAdapter, secondMockAdapter, settings } = await setup() const adapters = [mockAdapter.address, secondMockAdapter.address].sort(compareAddresses) await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) await giriGiriBashi.getHash(DOMAIN_ID, 21, adapters) - const head = await giriGiriBashi.heads(DOMAIN_ID) + const head = await giriGiriBashi.getHead(DOMAIN_ID) // revert on block before start ID await expect(giriGiriBashi.callStatic.challengeAdapter(DOMAIN_ID, 0, mockAdapter.address, { value: BOND })) @@ -360,9 +444,10 @@ describe("GiriGiriBashi", function () { const { giriGiriBashi, mockAdapter, secondMockAdapter, settings } = await setup() const adapters = [mockAdapter.address, secondMockAdapter.address].sort(compareAddresses) await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) await giriGiriBashi.getHash(DOMAIN_ID, 21, adapters) - const head = await giriGiriBashi.heads(DOMAIN_ID) + const head = await giriGiriBashi.getHead(DOMAIN_ID) expect( await giriGiriBashi.challengeAdapter(DOMAIN_ID, head - CHALLENGE_RANGE + 1, mockAdapter.address, { value: BOND, @@ -373,8 +458,9 @@ describe("GiriGiriBashi", function () { const { giriGiriBashi, mockAdapter, secondMockAdapter, settings } = await setup() const adapters = [mockAdapter.address, secondMockAdapter.address].sort(compareAddresses) await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) await giriGiriBashi.getHash(DOMAIN_ID, 21, adapters) - const head = await giriGiriBashi.heads(DOMAIN_ID) + const head = await giriGiriBashi.getHead(DOMAIN_ID) await expect( giriGiriBashi.challengeAdapter(DOMAIN_ID, head - CHALLENGE_RANGE + 1, mockAdapter.address, { @@ -395,15 +481,16 @@ describe("GiriGiriBashi", function () { const { giriGiriBashi, mockAdapter, secondMockAdapter, settings } = await setup() const adapters = [mockAdapter.address, secondMockAdapter.address].sort(compareAddresses) await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) await giriGiriBashi.getHash(DOMAIN_ID, 21, adapters) - const head = await giriGiriBashi.heads(DOMAIN_ID) + const head = await giriGiriBashi.getHead(DOMAIN_ID) const challengeBlock = head - CHALLENGE_RANGE + 1 await giriGiriBashi.challengeAdapter(DOMAIN_ID, challengeBlock, mockAdapter.address, { value: BOND, }) const challengeId = await giriGiriBashi.getChallengeId(DOMAIN_ID, challengeBlock, mockAdapter.address) - const challenge = await giriGiriBashi.challenges(challengeId) + const challenge = await giriGiriBashi.getChallenge(challengeId) const increaseAmount = challenge.timestamp.add(settings.timeout).sub(1) await network.provider.send("evm_setNextBlockTimestamp", [increaseAmount.toHexString()]) @@ -416,15 +503,16 @@ describe("GiriGiriBashi", function () { const { giriGiriBashi, mockAdapter, secondMockAdapter, settings, wallet } = await setup() const adapters = [mockAdapter.address, secondMockAdapter.address].sort(compareAddresses) await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) await giriGiriBashi.getHash(DOMAIN_ID, 21, adapters) - const head = await giriGiriBashi.heads(DOMAIN_ID) + const head = await giriGiriBashi.getHead(DOMAIN_ID) const challengeBlock = head - CHALLENGE_RANGE + 1 await giriGiriBashi.challengeAdapter(DOMAIN_ID, challengeBlock, mockAdapter.address, { value: BOND, }) const challengeId = await giriGiriBashi.getChallengeId(DOMAIN_ID, challengeBlock, mockAdapter.address) - const challenge = await giriGiriBashi.challenges(challengeId) + const challenge = await giriGiriBashi.getChallenge(challengeId) const increaseAmount = challenge.timestamp.add(settings.timeout).add(1) await network.provider.send("evm_setNextBlockTimestamp", [increaseAmount.toHexString()]) @@ -436,16 +524,17 @@ describe("GiriGiriBashi", function () { const newBalance = await ethers.provider.getBalance(wallet.address) await expect(newBalance).to.be.greaterThan(previousBalance) - const quarantined = (await giriGiriBashi.settings(mockAdapter.address)).quarantined + const quarantined = (await giriGiriBashi.getSettings(DOMAIN_ID, mockAdapter.address)).quarantined await expect(quarantined).to.equal(true) }) it("Keeps bond if _adapters + adapter equals threshold and agree", async function () { const { giriGiriBashi, mockAdapter, secondMockAdapter, settings } = await setup() const adapters = [mockAdapter.address, secondMockAdapter.address].sort(compareAddresses) await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) await giriGiriBashi.getHash(DOMAIN_ID, 1, adapters) - const head = await giriGiriBashi.heads(DOMAIN_ID) + const head = await giriGiriBashi.getHead(DOMAIN_ID) const challengeBlock = head.add(20) await giriGiriBashi.challengeAdapter(DOMAIN_ID, challengeBlock, mockAdapter.address, { value: BOND, @@ -454,16 +543,17 @@ describe("GiriGiriBashi", function () { const balanceBefore = await ethers.provider.getBalance(ADDRESS_TWO) await giriGiriBashi.resolveChallenge(DOMAIN_ID, challengeBlock, mockAdapter.address, [secondMockAdapter.address]) expect(await ethers.provider.getBalance(ADDRESS_TWO)).to.equal(balanceBefore.add(BOND)) - const quarantined = (await giriGiriBashi.settings(mockAdapter.address)).quarantined + const quarantined = (await giriGiriBashi.getSettings(DOMAIN_ID, mockAdapter.address)).quarantined expect(quarantined).to.equal(false) }) it("Reverts if _adapters + adapter equals threshold and disagree", async function () { const { giriGiriBashi, mockAdapter, secondMockAdapter, settings, hashi } = await setup() const adapters = [mockAdapter.address, secondMockAdapter.address].sort(compareAddresses) await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) await giriGiriBashi.getHash(DOMAIN_ID, 21, adapters) - const head = await giriGiriBashi.heads(DOMAIN_ID) + const head = await giriGiriBashi.getHead(DOMAIN_ID) const challengeBlock = head.add(1) await giriGiriBashi.challengeAdapter(DOMAIN_ID, challengeBlock, mockAdapter.address, { value: BOND, @@ -479,10 +569,11 @@ describe("GiriGiriBashi", function () { const { giriGiriBashi, mockAdapter, secondMockAdapter, thirdMockAdapter, settings } = await setup() let adapters = [mockAdapter.address, secondMockAdapter.address, thirdMockAdapter.address] await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) adapters = adapters.sort(compareAddresses) await giriGiriBashi.getHash(DOMAIN_ID, 1, adapters) - const head = await giriGiriBashi.heads(DOMAIN_ID) + const head = await giriGiriBashi.getHead(DOMAIN_ID) const challengeBlock = head.add(20) await giriGiriBashi.challengeAdapter(DOMAIN_ID, challengeBlock, mockAdapter.address, { value: BOND, @@ -497,17 +588,18 @@ describe("GiriGiriBashi", function () { [secondMockAdapter.address, thirdMockAdapter.address].sort(compareAddresses), ) expect(await ethers.provider.getBalance(ADDRESS_TWO)).to.equal(previousBalance.add(BOND)) - const quarantined = (await giriGiriBashi.settings(mockAdapter.address)).quarantined + const quarantined = (await giriGiriBashi.getSettings(DOMAIN_ID, mockAdapter.address)).quarantined expect(quarantined).to.equal(false) }) it("Quarantines adapter and returns bond if challenged adapter disagrees with canonical hash", async function () { const { giriGiriBashi, mockAdapter, secondMockAdapter, thirdMockAdapter, settings } = await setup() let adapters = [mockAdapter.address, secondMockAdapter.address, thirdMockAdapter.address] await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) adapters = adapters.sort(compareAddresses) await giriGiriBashi.getHash(DOMAIN_ID, 21, adapters) - const head = await giriGiriBashi.heads(DOMAIN_ID) + const head = await giriGiriBashi.getHead(DOMAIN_ID) const challengeBlock = head.add(1) await giriGiriBashi.challengeAdapter(DOMAIN_ID, challengeBlock, mockAdapter.address, { value: BOND, @@ -519,17 +611,18 @@ describe("GiriGiriBashi", function () { mockAdapter.address, [secondMockAdapter.address, thirdMockAdapter.address].sort(compareAddresses), ) - const quarantined = (await giriGiriBashi.settings(mockAdapter.address)).quarantined + const quarantined = (await giriGiriBashi.getSettings(DOMAIN_ID, mockAdapter.address)).quarantined await expect(quarantined).to.equal(true) }) it("Clears state after challenge is resolved", async function () { const { giriGiriBashi, mockAdapter, secondMockAdapter, thirdMockAdapter, settings } = await setup() let adapters = [mockAdapter.address, secondMockAdapter.address, thirdMockAdapter.address] await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) adapters = adapters.sort(compareAddresses) await giriGiriBashi.getHash(DOMAIN_ID, 21, adapters) - const head = await giriGiriBashi.heads(DOMAIN_ID) + const head = await giriGiriBashi.getHead(DOMAIN_ID) const challengeBlock = head.add(1) await giriGiriBashi.challengeAdapter(DOMAIN_ID, challengeBlock, mockAdapter.address, { value: BOND, @@ -541,10 +634,10 @@ describe("GiriGiriBashi", function () { mockAdapter.address, [secondMockAdapter.address, thirdMockAdapter.address].sort(compareAddresses), ) - const quarantined = (await giriGiriBashi.settings(mockAdapter.address)).quarantined + const quarantined = (await giriGiriBashi.getSettings(DOMAIN_ID, mockAdapter.address)).quarantined expect(quarantined).to.equal(true) const challengeId = await giriGiriBashi.getChallengeId(DOMAIN_ID, challengeBlock, mockAdapter.address) - const challenge = await giriGiriBashi.challenges(challengeId) + const challenge = await giriGiriBashi.getChallenge(challengeId) expect(challenge.challenger).to.equal(ADDRESS_ZERO) expect(challenge.timestamp).to.equal(0) expect(challenge.bond).to.equal(0) @@ -553,9 +646,10 @@ describe("GiriGiriBashi", function () { const { giriGiriBashi, mockAdapter, secondMockAdapter, thirdMockAdapter, settings, wallet } = await setup() const adapters = [mockAdapter.address, secondMockAdapter.address, thirdMockAdapter.address].sort(compareAddresses) await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) await giriGiriBashi.getHash(DOMAIN_ID, 21, adapters) - const head = await giriGiriBashi.heads(DOMAIN_ID) + const head = await giriGiriBashi.getHead(DOMAIN_ID) const challengeBlock = head.add(1) await giriGiriBashi.challengeAdapter(DOMAIN_ID, challengeBlock, mockAdapter.address, { value: BOND, @@ -580,26 +674,38 @@ describe("GiriGiriBashi", function () { const { giriGiriBashi, mockAdapter, secondMockAdapter, thirdMockAdapter, settings } = await setup() const adapters = [mockAdapter.address, secondMockAdapter.address, thirdMockAdapter.address].sort(compareAddresses) await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) await expect(giriGiriBashi.callStatic.declareNoConfidence(DOMAIN_ID, 20, [mockAdapter.address])) .to.be.revertedWithCustomError(giriGiriBashi, "CannotProveNoConfidence") .withArgs(DOMAIN_ID, 20, [mockAdapter.address]) }) + it("Reverts if the majority of adapters report the hash = 0", async function () { + const { giriGiriBashi, mockAdapter, secondMockAdapter, thirdMockAdapter, settings } = await setup() + const adapters = [mockAdapter.address, secondMockAdapter.address, thirdMockAdapter.address].sort(compareAddresses) + await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) + await expect(giriGiriBashi.callStatic.declareNoConfidence(DOMAIN_ID, 25, adapters)) + .to.be.revertedWithCustomError(giriGiriBashi, "CannotProveNoConfidence") + .withArgs(DOMAIN_ID, 25, adapters) + }) it("Reverts if any of the provided adapters agree", async function () { const { giriGiriBashi, mockAdapter, secondMockAdapter, thirdMockAdapter, settings } = await setup() const adapters = [mockAdapter.address, secondMockAdapter.address, thirdMockAdapter.address].sort(compareAddresses) - const adaptersThatAgree = [secondMockAdapter.address, thirdMockAdapter.address].sort(compareAddresses) await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings, settings]) - await expect(giriGiriBashi.callStatic.declareNoConfidence(DOMAIN_ID, 22, adapters)) - .to.be.revertedWithCustomError(giriGiriBashi, "AdaptersAgreed") - .withArgs(adaptersThatAgree[0], adaptersThatAgree[1]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) + await expect(giriGiriBashi.callStatic.declareNoConfidence(DOMAIN_ID, 22, adapters)).to.be.revertedWithCustomError( + giriGiriBashi, + "AdaptersAgreed", + ) }) it("Clears state for domain", async function () { const { giriGiriBashi, mockAdapter, secondMockAdapter, thirdMockAdapter, settings } = await setup() const adapters = [mockAdapter.address, secondMockAdapter.address, thirdMockAdapter.address].sort(compareAddresses) await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) expect(await giriGiriBashi.declareNoConfidence(DOMAIN_ID, 20, adapters)) - const domain = await giriGiriBashi.domains(DOMAIN_ID) - const challengeRange = await giriGiriBashi.challengeRanges(DOMAIN_ID) + const domain = await giriGiriBashi.getDomain(DOMAIN_ID) + const challengeRange = await giriGiriBashi.getChallengeRange(DOMAIN_ID) expect(domain.threshold).to.equal(ethers.constants.MaxUint256) expect(challengeRange).to.equal(0) }) @@ -635,7 +741,7 @@ describe("GiriGiriBashi", function () { it("Sets challenge range for given domain", async function () { const { giriGiriBashi } = await setup() expect(await giriGiriBashi.setChallengeRange(2, CHALLENGE_RANGE)) - const challengeRange = await giriGiriBashi.challengeRanges(2) + const challengeRange = await giriGiriBashi.getChallengeRange(2) expect(challengeRange).to.equal(CHALLENGE_RANGE) }) it("Emits the ChallengeRangeUpdated event", async function () { @@ -654,6 +760,7 @@ describe("GiriGiriBashi", function () { [mockAdapter.address, secondMockAdapter.address], [settings, settings], ) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) await expect( giriGiriBashi.replaceQuarantinedAdapters( DOMAIN_ID, @@ -686,6 +793,7 @@ describe("GiriGiriBashi", function () { [mockAdapter.address, secondMockAdapter.address], [settings, settings], ) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) await expect( giriGiriBashi.replaceQuarantinedAdapters( DOMAIN_ID, @@ -699,10 +807,11 @@ describe("GiriGiriBashi", function () { const { giriGiriBashi, mockAdapter, secondMockAdapter, thirdMockAdapter, settings } = await setup() let adapters = [mockAdapter.address, secondMockAdapter.address, thirdMockAdapter.address] await giriGiriBashi.enableAdapters(DOMAIN_ID, adapters, [settings, settings, settings]) + await giriGiriBashi.setThreshold(DOMAIN_ID, 2) adapters = adapters.sort(compareAddresses) await giriGiriBashi.getHash(DOMAIN_ID, 21, adapters) - const head = await giriGiriBashi.heads(DOMAIN_ID) + const head = await giriGiriBashi.getHead(DOMAIN_ID) const challengeBlock = head.add(1) await giriGiriBashi.challengeAdapter(DOMAIN_ID, challengeBlock, mockAdapter.address, { value: BOND, @@ -717,7 +826,7 @@ describe("GiriGiriBashi", function () { expect( await giriGiriBashi.replaceQuarantinedAdapters(DOMAIN_ID, [mockAdapter.address], [ADDRESS_TWO], [settings]), ) - const adapterSettings = await giriGiriBashi.settings(ADDRESS_TWO) + const adapterSettings = await giriGiriBashi.getSettings(DOMAIN_ID, ADDRESS_TWO) expect(adapterSettings.quarantined).to.deep.equal(settings.quarantined) expect(adapterSettings.minimumBond).to.deep.equal(settings.minimumBond) expect(adapterSettings.startId).to.deep.equal(settings.startId)