diff --git a/packages/protocol/contracts/bridge/Bridge.sol b/packages/protocol/contracts/bridge/Bridge.sol index 89980a9bb5..0383d6fb98 100644 --- a/packages/protocol/contracts/bridge/Bridge.sol +++ b/packages/protocol/contracts/bridge/Bridge.sol @@ -9,6 +9,7 @@ pragma solidity ^0.8.18; import {AddressResolver} from "../common/AddressResolver.sol"; import {EssentialContract} from "../common/EssentialContract.sol"; import {IBridge} from "./IBridge.sol"; +import {BridgeCustomErrors} from "./BridgeCustomErrors.sol"; import {LibBridgeData} from "./libs/LibBridgeData.sol"; import {LibBridgeProcess} from "./libs/LibBridgeProcess.sol"; import {LibBridgeRelease} from "./libs/LibBridgeRelease.sol"; @@ -21,7 +22,7 @@ import {LibBridgeStatus} from "./libs/LibBridgeStatus.sol"; * which calls the library implementations. See _IBridge_ for more details. * @dev The code hash for the same address on L1 and L2 may be different. */ -contract Bridge is EssentialContract, IBridge { +contract Bridge is EssentialContract, IBridge, BridgeCustomErrors { using LibBridgeData for Message; /********************* @@ -49,12 +50,13 @@ contract Bridge is EssentialContract, IBridge { /// Allow Bridge to receive ETH from the TokenVault or EtherVault. receive() external payable { - require( - msg.sender == resolve("token_vault", true) || - msg.sender == resolve("ether_vault", true) || - msg.sender == owner(), - "B:receive" - ); + if ( + msg.sender != resolve("token_vault", true) && + msg.sender != resolve("ether_vault", true) && + msg.sender != owner() + ) { + revert B_CANNOT_RECEIVE(); + } } /// @dev Initializer to be called after being deployed behind a proxy. diff --git a/packages/protocol/contracts/bridge/BridgeCustomErrors.sol b/packages/protocol/contracts/bridge/BridgeCustomErrors.sol new file mode 100644 index 0000000000..a6d725700a --- /dev/null +++ b/packages/protocol/contracts/bridge/BridgeCustomErrors.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT +// _____ _ _ _ _ +// |_ _|_ _(_) |_____ | | __ _| |__ ___ +// | |/ _` | | / / _ \ | |__/ _` | '_ (_-< +// |_|\__,_|_|_\_\___/ |____\__,_|_.__/__/ + +pragma solidity ^0.8.18; + +abstract contract BridgeCustomErrors { + error B_CANNOT_RECEIVE(); + error B_DENIED(); + error B_ERC20_CANNOT_RECEIVE(); + error B_ETHER_RELEASED_ALREADY(); + error B_EV_DO_NOT_BURN(); + error B_EV_NOT_AUTHORIZED(); + error B_EV_PARAM(); + error B_FAILED_TRANSFER(); + error B_FORBIDDEN(); + error B_GAS_LIMIT(); + error B_INCORRECT_VALUE(); + error B_INIT_PARAM_ERROR(); + error B_MSG_HASH_NULL(); + error B_MSG_NON_RETRIABLE(); + error B_MSG_NOT_FAILED(); + error B_NULL_APP_ADDR(); + error B_OWNER_IS_NULL(); + error B_SIGNAL_NOT_RECEIVED(); + error B_STATUS_MISMTACH(); + error B_WRONG_CHAIN_ID(); + error B_WRONG_TO_ADDRESS(); + error B_ZERO_SIGNAL(); +} diff --git a/packages/protocol/contracts/bridge/BridgedERC20.sol b/packages/protocol/contracts/bridge/BridgedERC20.sol index 64bcf33ccc..9122252e82 100644 --- a/packages/protocol/contracts/bridge/BridgedERC20.sol +++ b/packages/protocol/contracts/bridge/BridgedERC20.sol @@ -16,12 +16,14 @@ import { import {EssentialContract} from "../common/EssentialContract.sol"; import {ERC20Upgradeable} from "../thirdparty/ERC20Upgradeable.sol"; +import {BridgeCustomErrors} from "./BridgeCustomErrors.sol"; contract BridgedERC20 is EssentialContract, IERC20Upgradeable, IERC20MetadataUpgradeable, - ERC20Upgradeable + ERC20Upgradeable, + BridgeCustomErrors { address public srcToken; uint256 public srcChainId; @@ -41,14 +43,15 @@ contract BridgedERC20 is string memory _symbol, string memory _name ) external initializer { - require( - _srcToken != address(0) && - _srcChainId != 0 && - _srcChainId != block.chainid && - bytes(_symbol).length > 0 && - bytes(_name).length > 0, - "BE:params" - ); + if ( + _srcToken == address(0) || + _srcChainId == 0 || + _srcChainId == block.chainid || + bytes(_symbol).length == 0 || + bytes(_name).length == 0 + ) { + revert B_INIT_PARAM_ERROR(); + } EssentialContract._init(_addressManager); ERC20Upgradeable.__ERC20_init({ name_: _name, @@ -83,7 +86,9 @@ contract BridgedERC20 is address to, uint256 amount ) public override(ERC20Upgradeable, IERC20Upgradeable) returns (bool) { - require(to != address(this), "BE:to"); + if (to == address(this)) { + revert B_ERC20_CANNOT_RECEIVE(); + } return ERC20Upgradeable.transfer(to, amount); } @@ -95,7 +100,9 @@ contract BridgedERC20 is address to, uint256 amount ) public override(ERC20Upgradeable, IERC20Upgradeable) returns (bool) { - require(to != address(this), "BE:to"); + if (to == address(this)) { + revert B_ERC20_CANNOT_RECEIVE(); + } return ERC20Upgradeable.transferFrom(from, to, amount); } diff --git a/packages/protocol/contracts/bridge/EtherVault.sol b/packages/protocol/contracts/bridge/EtherVault.sol index b271da003b..f34fd3b9dd 100644 --- a/packages/protocol/contracts/bridge/EtherVault.sol +++ b/packages/protocol/contracts/bridge/EtherVault.sol @@ -16,6 +16,7 @@ import { import {EssentialContract} from "../common/EssentialContract.sol"; import {LibAddress} from "../libs/LibAddress.sol"; +import {BridgeCustomErrors} from "./BridgeCustomErrors.sol"; /** * EtherVault is a special vault contract that: @@ -23,7 +24,7 @@ import {LibAddress} from "../libs/LibAddress.sol"; * - Allows the contract owner to authorize addresses. * - Allows authorized addresses to send/release Ether. */ -contract EtherVault is EssentialContract { +contract EtherVault is EssentialContract, BridgeCustomErrors { using LibAddress for address; /********************* @@ -46,7 +47,9 @@ contract EtherVault is EssentialContract { *********************/ modifier onlyAuthorized() { - require(isAuthorized(msg.sender), "EV:denied"); + if (!isAuthorized(msg.sender)) { + revert B_EV_NOT_AUTHORIZED(); + } _; } @@ -56,10 +59,9 @@ contract EtherVault is EssentialContract { receive() external payable { // EthVault's balance must == 0 OR the sender isAuthorized. - require( - address(this).balance == 0 || isAuthorized(msg.sender), - "EV:denied" - ); + if (address(this).balance != 0 && !isAuthorized(msg.sender)) { + revert B_EV_NOT_AUTHORIZED(); + } } function init(address addressManager) external initializer { @@ -90,7 +92,9 @@ contract EtherVault is EssentialContract { address recipient, uint256 amount ) public onlyAuthorized nonReentrant { - require(recipient != address(0), "EV:recipient"); + if (recipient == address(0)) { + revert B_EV_DO_NOT_BURN(); + } recipient.sendEther(amount); emit EtherReleased(recipient, amount); } @@ -101,10 +105,9 @@ contract EtherVault is EssentialContract { * @param authorized Authorized status to set. */ function authorize(address addr, bool authorized) public onlyOwner { - require( - addr != address(0) && _authorizedAddrs[addr] != authorized, - "EV:param" - ); + if (addr == address(0) || _authorizedAddrs[addr] == authorized) { + revert B_EV_PARAM(); + } _authorizedAddrs[addr] = authorized; emit Authorized(addr, authorized); } diff --git a/packages/protocol/contracts/bridge/libs/LibBridgeInvoke.sol b/packages/protocol/contracts/bridge/libs/LibBridgeInvoke.sol index a7ba55ad1a..5bfff9dc5c 100644 --- a/packages/protocol/contracts/bridge/libs/LibBridgeInvoke.sol +++ b/packages/protocol/contracts/bridge/libs/LibBridgeInvoke.sol @@ -12,6 +12,8 @@ library LibBridgeInvoke { using LibAddress for address; using LibBridgeData for IBridge.Message; + error B_GAS_LIMIT(); + /********************* * Internal Functions* *********************/ @@ -22,7 +24,9 @@ library LibBridgeInvoke { bytes32 msgHash, uint256 gasLimit ) internal returns (bool success) { - require(gasLimit > 0, "B:gasLimit"); + if (gasLimit == 0) { + revert B_GAS_LIMIT(); + } state.ctx = IBridge.Context({ msgHash: msgHash, diff --git a/packages/protocol/contracts/bridge/libs/LibBridgeProcess.sol b/packages/protocol/contracts/bridge/libs/LibBridgeProcess.sol index 7f9ca4103c..23f25c71e1 100644 --- a/packages/protocol/contracts/bridge/libs/LibBridgeProcess.sol +++ b/packages/protocol/contracts/bridge/libs/LibBridgeProcess.sol @@ -26,6 +26,11 @@ library LibBridgeProcess { using LibBridgeData for IBridge.Message; using LibBridgeData for LibBridgeData.State; + error B_FORBIDDEN(); + error B_STATUS_MISMTACH(); + error B_SIGNAL_NOT_RECEIVED(); + error B_WRONG_CHAIN_ID(); + /** * Process the bridge message on the destination chain. It can be called by * any address, including `message.owner`. It starts by hashing the message, @@ -45,20 +50,23 @@ library LibBridgeProcess { bytes calldata proof ) external { // If the gas limit is set to zero, only the owner can process the message. - if (message.gasLimit == 0) { - require(msg.sender == message.owner, "B:forbidden"); + if (message.gasLimit == 0 && msg.sender != message.owner) { + revert B_FORBIDDEN(); } - require(message.destChainId == block.chainid, "B:destChainId"); + if (message.destChainId != block.chainid) { + revert B_WRONG_CHAIN_ID(); + } // The message status must be "NEW"; "RETRIABLE" is handled in // LibBridgeRetry.sol. bytes32 msgHash = message.hashMessage(); - require( - LibBridgeStatus.getMessageStatus(msgHash) == - LibBridgeStatus.MessageStatus.NEW, - "B:status" - ); + if ( + LibBridgeStatus.getMessageStatus(msgHash) != + LibBridgeStatus.MessageStatus.NEW + ) { + revert B_STATUS_MISMTACH(); + } // Message must have been "received" on the destChain (current chain) address srcBridge = resolver.resolve( message.srcChainId, @@ -66,16 +74,17 @@ library LibBridgeProcess { false ); - require( - ISignalService(resolver.resolve("signal_service", false)) + if ( + !ISignalService(resolver.resolve("signal_service", false)) .isSignalReceived({ srcChainId: message.srcChainId, app: srcBridge, signal: msgHash, proof: proof - }), - "B:notReceived" - ); + }) + ) { + revert B_SIGNAL_NOT_RECEIVED(); + } // We retrieve the necessary ether from EtherVault if receiving on // Taiko, otherwise it is already available in this Bridge. diff --git a/packages/protocol/contracts/bridge/libs/LibBridgeRelease.sol b/packages/protocol/contracts/bridge/libs/LibBridgeRelease.sol index e52ff88b7e..77314312b1 100644 --- a/packages/protocol/contracts/bridge/libs/LibBridgeRelease.sol +++ b/packages/protocol/contracts/bridge/libs/LibBridgeRelease.sol @@ -15,6 +15,12 @@ import {AddressResolver} from "../../common/AddressResolver.sol"; library LibBridgeRelease { using LibBridgeData for IBridge.Message; + error B_OWNER_IS_NULL(); + error B_WRONG_CHAIN_ID(); + error B_ETHER_RELEASED_ALREADY(); + error B_MSG_NOT_FAILED(); + error B_FAILED_TRANSFER(); + event EtherReleased(bytes32 indexed msgHash, address to, uint256 amount); /** @@ -28,20 +34,30 @@ library LibBridgeRelease { IBridge.Message calldata message, bytes calldata proof ) internal { - require(message.owner != address(0), "B:owner"); - require(message.srcChainId == block.chainid, "B:srcChainId"); + if (message.owner == address(0)) { + revert B_OWNER_IS_NULL(); + } + + if (message.srcChainId != block.chainid) { + revert B_WRONG_CHAIN_ID(); + } bytes32 msgHash = message.hashMessage(); - require(state.etherReleased[msgHash] == false, "B:etherReleased"); - require( - LibBridgeStatus.isMessageFailed( + + if (state.etherReleased[msgHash] == true) { + revert B_ETHER_RELEASED_ALREADY(); + } + + if ( + !LibBridgeStatus.isMessageFailed( resolver, msgHash, message.destChainId, proof - ), - "B:notFailed" - ); + ) + ) { + revert B_MSG_NOT_FAILED(); + } state.etherReleased[msgHash] = true; @@ -58,7 +74,9 @@ library LibBridgeRelease { } else { // if on Ethereum (bool success, ) = message.owner.call{value: releaseAmount}(""); - require(success, "B:transfer"); + if (!success) { + revert B_FAILED_TRANSFER(); + } } } emit EtherReleased(msgHash, message.owner, releaseAmount); diff --git a/packages/protocol/contracts/bridge/libs/LibBridgeRetry.sol b/packages/protocol/contracts/bridge/libs/LibBridgeRetry.sol index 20e709beda..e4153486a6 100644 --- a/packages/protocol/contracts/bridge/libs/LibBridgeRetry.sol +++ b/packages/protocol/contracts/bridge/libs/LibBridgeRetry.sol @@ -23,6 +23,9 @@ library LibBridgeRetry { using LibBridgeData for IBridge.Message; using LibBridgeData for LibBridgeData.State; + error B_DENIED(); + error B_MSG_NON_RETRIABLE(); + /** * Retries to invoke the messageCall, the owner has already been sent Ether. * - This function can be called by any address, including `message.owner`. @@ -46,15 +49,16 @@ library LibBridgeRetry { // If the gasLimit is not set to 0 or isLastAttempt is true, the // address calling this function must be message.owner. if (message.gasLimit == 0 || isLastAttempt) { - require(msg.sender == message.owner, "B:denied"); + if (msg.sender != message.owner) revert B_DENIED(); } bytes32 msgHash = message.hashMessage(); - require( - LibBridgeStatus.getMessageStatus(msgHash) == - LibBridgeStatus.MessageStatus.RETRIABLE, - "B:notFound" - ); + if ( + LibBridgeStatus.getMessageStatus(msgHash) != + LibBridgeStatus.MessageStatus.RETRIABLE + ) { + revert B_MSG_NON_RETRIABLE(); + } address ethVault = resolver.resolve("ether_vault", true); if (ethVault != address(0)) { diff --git a/packages/protocol/contracts/bridge/libs/LibBridgeSend.sol b/packages/protocol/contracts/bridge/libs/LibBridgeSend.sol index d4d6172c70..a38fa0425f 100644 --- a/packages/protocol/contracts/bridge/libs/LibBridgeSend.sol +++ b/packages/protocol/contracts/bridge/libs/LibBridgeSend.sol @@ -21,6 +21,11 @@ library LibBridgeSend { using LibAddress for address; using LibBridgeData for IBridge.Message; + error B_OWNER_IS_NULL(); + error B_WRONG_CHAIN_ID(); + error B_WRONG_TO_ADDRESS(); + error B_INCORRECT_VALUE(); + /** * Send a message to the Bridge with the details of the request. The Bridge * takes custody of the funds, unless the source chain is Taiko, in which @@ -41,22 +46,29 @@ library LibBridgeSend { AddressResolver resolver, IBridge.Message memory message ) internal returns (bytes32 msgHash) { - require(message.owner != address(0), "B:owner"); + if (message.owner == address(0)) { + revert B_OWNER_IS_NULL(); + } (bool destChainEnabled, address destChain) = isDestChainEnabled( resolver, message.destChainId ); - require( - destChainEnabled && message.destChainId != block.chainid, - "B:destChainId" - ); - require(message.to != address(0) && message.to != destChain, "B:to"); + + if (!destChainEnabled || message.destChainId == block.chainid) { + revert B_WRONG_CHAIN_ID(); + } + if (message.to == address(0) || message.to == destChain) { + revert B_WRONG_TO_ADDRESS(); + } uint256 expectedAmount = message.depositValue + message.callValue + message.processingFee; - require(expectedAmount == msg.value, "B:value"); + + if (expectedAmount != msg.value) { + revert B_INCORRECT_VALUE(); + } // If on Taiko, send the expectedAmount to the EtherVault. Otherwise, // store it here on the Bridge. Processing will release Ether from the diff --git a/packages/protocol/contracts/bridge/libs/LibBridgeStatus.sol b/packages/protocol/contracts/bridge/libs/LibBridgeStatus.sol index e43123c4ed..c99bc4b706 100644 --- a/packages/protocol/contracts/bridge/libs/LibBridgeStatus.sol +++ b/packages/protocol/contracts/bridge/libs/LibBridgeStatus.sol @@ -28,6 +28,9 @@ library LibBridgeStatus { address transactor ); + error B_WRONG_CHAIN_ID(); + error B_MSG_HASH_NULL(); + /** * @dev If messageStatus is same as in the messageStatus mapping, * does nothing. @@ -65,8 +68,12 @@ library LibBridgeStatus { uint256 destChainId, bytes calldata proof ) internal view returns (bool) { - require(destChainId != block.chainid, "B:destChainId"); - require(msgHash != 0, "B:msgHash"); + if (destChainId == block.chainid) { + revert B_WRONG_CHAIN_ID(); + } + if (msgHash == 0x0) { + revert B_MSG_HASH_NULL(); + } LibBridgeData.StatusProof memory sp = abi.decode( proof, diff --git a/packages/protocol/contracts/signal/SignalService.sol b/packages/protocol/contracts/signal/SignalService.sol index 051c2eb516..fe2a9a6b74 100644 --- a/packages/protocol/contracts/signal/SignalService.sol +++ b/packages/protocol/contracts/signal/SignalService.sol @@ -20,13 +20,19 @@ contract SignalService is ISignalService, EssentialContract { bytes proof; } + error B_ZERO_SIGNAL(); + error B_NULL_APP_ADDR(); + error B_WRONG_CHAIN_ID(); + /// @dev Initializer to be called after being deployed behind a proxy. function init(address _addressManager) external initializer { EssentialContract._init(_addressManager); } function sendSignal(bytes32 signal) public returns (bytes32 storageSlot) { - require(signal != 0, "B:signal"); + if (signal == 0) { + revert B_ZERO_SIGNAL(); + } storageSlot = getSignalSlot(msg.sender, signal); assembly { @@ -38,8 +44,13 @@ contract SignalService is ISignalService, EssentialContract { address app, bytes32 signal ) public view returns (bool) { - require(app != address(0), "B:app"); - require(signal != 0, "B:signal"); + if (app == address(0)) { + revert B_NULL_APP_ADDR(); + } + + if (signal == 0) { + revert B_ZERO_SIGNAL(); + } bytes32 slot = getSignalSlot(app, signal); uint256 value; @@ -55,9 +66,17 @@ contract SignalService is ISignalService, EssentialContract { bytes32 signal, bytes calldata proof ) public view returns (bool) { - require(srcChainId != block.chainid, "B:srcChainId"); - require(app != address(0), "B:app"); - require(signal != 0, "B:signal"); + if (srcChainId == block.chainid) { + revert B_WRONG_CHAIN_ID(); + } + + if (app == address(0)) { + revert B_NULL_APP_ADDR(); + } + + if (signal == 0) { + revert B_ZERO_SIGNAL(); + } SignalProof memory sp = abi.decode(proof, (SignalProof)); // Resolve the TaikoL1 or TaikoL2 contract if on Ethereum or Taiko. diff --git a/packages/protocol/hardhat.config.ts b/packages/protocol/hardhat.config.ts index b4d0fb695c..fc953d6986 100644 --- a/packages/protocol/hardhat.config.ts +++ b/packages/protocol/hardhat.config.ts @@ -29,7 +29,10 @@ const config: HardhatUserConfig = { }, gasReporter: { currency: "USD", - enabled: process.env.REPORT_GAS === "true", + enabled: true, + gasPriceApi: + "https://api.etherscan.io/api?module=proxy&action=eth_gasPrice", + token: "ETH", }, mocha: { timeout: 300000, diff --git a/packages/protocol/test/bridge/Bridge.integration.test.ts b/packages/protocol/test/bridge/Bridge.integration.test.ts index 27e4ea2d26..6e28ef2b0f 100644 --- a/packages/protocol/test/bridge/Bridge.integration.test.ts +++ b/packages/protocol/test/bridge/Bridge.integration.test.ts @@ -16,6 +16,7 @@ import { sendAndProcessMessage, sendMessage, } from "../utils/bridge"; +import { txShouldRevertWithCustomError } from "../utils/errors"; // import { randomBytes32 } from "../utils/bytes"; import { Message } from "../utils/message"; import { @@ -170,11 +171,17 @@ describe("integrationbridge:Bridge", function () { expect(msgHash).not.to.be.eq(ethers.constants.HashZero); - await expect( - l2Bridge - .connect(l2Signer) - .processMessage(m, ethers.constants.HashZero) - ).to.be.revertedWith("B:forbidden"); + txShouldRevertWithCustomError( + ( + await l2Bridge + .connect(l2Signer) + .processMessage(m, ethers.constants.HashZero, { + gasLimit: 1000000, + }) + ).wait(1), + l2Provider, + "B_FORBIDDEN()" + ); }); it("should throw if message.destChainId is not equal to current block.chainId", async function () { @@ -194,9 +201,17 @@ describe("integrationbridge:Bridge", function () { memo: "", }; - await expect( - l2Bridge.processMessage(m, ethers.constants.HashZero) - ).to.be.revertedWith("B:destChainId"); + txShouldRevertWithCustomError( + ( + await l2Bridge + .connect(l2Signer) + .processMessage(m, ethers.constants.HashZero, { + gasLimit: 1000000, + }) + ).wait(1), + l2Provider, + "B_WRONG_CHAIN_ID()" + ); }); it("should throw if messageStatus of message is != NEW", async function () { @@ -210,9 +225,17 @@ describe("integrationbridge:Bridge", function () { ); // recalling this process should be prevented as it's status is no longer NEW - await expect( - l2Bridge.processMessage(message, signalProof) - ).to.be.revertedWith("B:status"); + txShouldRevertWithCustomError( + ( + await l2Bridge + .connect(l2Signer) + .processMessage(message, signalProof, { + gasLimit: 1000000, + }) + ).wait(1), + l2Provider, + "B_STATUS_MISMATCH()" + ); }); it("should throw if message signalproof is not valid", async function () { @@ -231,9 +254,17 @@ describe("integrationbridge:Bridge", function () { blockHeader ); - await expect( - l2Bridge.processMessage(m, signalProof) - ).to.be.revertedWith("B:notReceived"); + txShouldRevertWithCustomError( + ( + await l2Bridge + .connect(l2Signer) + .processMessage(m, signalProof, { + gasLimit: 1000000, + }) + ).wait(1), + l2Provider, + "B_SIGNAL_NOT_RECEIVED()" + ); }); it("should throw if message has not been received", async function () { @@ -274,9 +305,17 @@ describe("integrationbridge:Bridge", function () { blockHeader ); - await expect( - l2Bridge.processMessage(message, signalProof) - ).to.be.revertedWith("B:notReceived"); + txShouldRevertWithCustomError( + ( + await l2Bridge + .connect(l2Signer) + .processMessage(message, signalProof, { + gasLimit: 1000000, + }) + ).wait(1), + l2Provider, + "B_SIGNAL_NOT_RECEIVED()" + ); }); it("processes a message when the signal has been verified from the sending chain", async () => { @@ -310,6 +349,18 @@ describe("integrationbridge:Bridge", function () { expect(storageValue).to.be.eq( "0x0000000000000000000000000000000000000000000000000000000000000001" ); + + txShouldRevertWithCustomError( + ( + await l2Bridge + .connect(l2Signer) + .processMessage(m, ethers.constants.HashZero, { + gasLimit: 1000000, + }) + ).wait(1), + l2Provider, + "B_WRONG_CHAIN_ID()" + ); }); }); @@ -445,7 +496,7 @@ describe("integrationbridge:Bridge", function () { enabledDestChainId, ethers.constants.HashZero ) - ).to.be.revertedWith("B:destChainId"); + ).to.be.revertedWith("B_WRONG_CHAIN_ID()"); }); it("should revert if msgHash == 0", async function () { @@ -455,7 +506,7 @@ describe("integrationbridge:Bridge", function () { srcChainId, ethers.constants.HashZero ) - ).to.be.revertedWith("B:msgHash"); + ).to.be.revertedWith("B_MSG_HASH_NULL()"); }); it("should return false if headerHash hasn't been synced", async function () { diff --git a/packages/protocol/test/bridge/Bridge.test.ts b/packages/protocol/test/bridge/Bridge.test.ts index 40b93dd54c..51537657ac 100644 --- a/packages/protocol/test/bridge/Bridge.test.ts +++ b/packages/protocol/test/bridge/Bridge.test.ts @@ -61,7 +61,7 @@ describe("Bridge", function () { }; await expect(l1Bridge.sendMessage(message)).to.be.revertedWith( - "B:owner" + "B_OWNER_IS_NULL()" ); }); @@ -84,7 +84,7 @@ describe("Bridge", function () { }; await expect(l1Bridge.sendMessage(message)).to.be.revertedWith( - "B:destChainId" + "B_WRONG_CHAIN_ID()" ); }); @@ -106,7 +106,7 @@ describe("Bridge", function () { }; await expect(l1Bridge.sendMessage(message)).to.be.revertedWith( - "B:destChainId" + "B_WRONG_CHAIN_ID()" ); }); @@ -128,7 +128,7 @@ describe("Bridge", function () { }; await expect(l1Bridge.sendMessage(message)).to.be.revertedWith( - "B:value" + "B_INCORRECT_VALUE()" ); }); @@ -275,7 +275,7 @@ describe("Bridge", function () { await expect( l1Bridge.processMessage(message, ethers.constants.HashZero) - ).to.be.revertedWith("B:forbidden"); + ).to.be.revertedWith("B_FORBIDDEN()"); }); it("throws message.destChainId is not block.chainId", async () => { @@ -297,7 +297,7 @@ describe("Bridge", function () { await expect( l1Bridge.processMessage(message, ethers.constants.HashZero) - ).to.be.revertedWith("B:destChainId"); + ).to.be.revertedWith("B_WRONG_CHAIN_ID()"); }); }); }); diff --git a/packages/protocol/test/bridge/BridgedERC20.test.ts b/packages/protocol/test/bridge/BridgedERC20.test.ts index 209fedb058..e4ddb4e2c6 100644 --- a/packages/protocol/test/bridge/BridgedERC20.test.ts +++ b/packages/protocol/test/bridge/BridgedERC20.test.ts @@ -78,7 +78,7 @@ describe("BridgedERC20", function () { "SYMB", "Name" ) - ).not.to.be.revertedWith("BE:params"); + ).not.to.be.revertedWith("BRIDGE_INIT_PARAM_ERROR()"); }); it("throws when _srcToken is address 0 ", async () => { @@ -93,7 +93,7 @@ describe("BridgedERC20", function () { "SYMB", "Name" ) - ).to.be.revertedWith("BE:params"); + ).to.be.revertedWith("B_INIT_PARAM_ERROR()"); }); it("throws when _srcChainId is 0", async () => { @@ -108,7 +108,7 @@ describe("BridgedERC20", function () { "SYMB", "Name" ) - ).to.be.revertedWith("BE:params"); + ).to.be.revertedWith("B_INIT_PARAM_ERROR()"); }); it("throws when _symbol is 0 length", async () => { @@ -123,7 +123,7 @@ describe("BridgedERC20", function () { "", "Name" ) - ).to.be.revertedWith("BE:params"); + ).to.be.revertedWith("B_INIT_PARAM_ERROR()"); }); it("throws when _name is 0 length", async () => { @@ -138,7 +138,7 @@ describe("BridgedERC20", function () { "SYMB", "" ) - ).to.be.revertedWith("BE:params"); + ).to.be.revertedWith("B_INIT_PARAM_ERROR()"); }); it("throws when _srcChainId is equal to block.chainid", async () => { @@ -154,7 +154,7 @@ describe("BridgedERC20", function () { "SYMB", "name" ) - ).to.be.revertedWith("BE:params"); + ).to.be.revertedWith("B_INIT_PARAM_ERROR()"); }); }); @@ -234,7 +234,7 @@ describe("BridgedERC20", function () { erc20 .connect(accountWithTokens) .transferFrom(accountWithTokens.address, erc20.address, 1) - ).to.be.revertedWith("BE:to"); + ).to.be.revertedWith("B_ERC20_CANNOT_RECEIVE()"); }); }); @@ -242,7 +242,7 @@ describe("BridgedERC20", function () { it("throws when trying to transfer to itself", async () => { await expect( erc20.connect(accountWithTokens).transfer(erc20.address, 1) - ).to.be.revertedWith("BE:to"); + ).to.be.revertedWith("B_ERC20_CANNOT_RECEIVE()"); }); it("throws when trying to transfer amount greater than holder owns", async () => { diff --git a/packages/protocol/test/bridge/libs/LibBridgeInvoke.test.ts b/packages/protocol/test/bridge/libs/LibBridgeInvoke.test.ts index c705f66ed6..3df2d1fb78 100644 --- a/packages/protocol/test/bridge/libs/LibBridgeInvoke.test.ts +++ b/packages/protocol/test/bridge/libs/LibBridgeInvoke.test.ts @@ -51,7 +51,7 @@ describe("LibBridgeInvoke", function () { await expect( libInvoke.invokeMessageCall(message, signal, message.gasLimit) - ).to.be.revertedWith("B:gasLimit"); + ).to.be.revertedWith("B_GAS_LIMIT()"); }); it("should emit event with success false if message does not actually invoke", async function () { diff --git a/packages/protocol/test/bridge/libs/LibBridgeProcess.test.ts b/packages/protocol/test/bridge/libs/LibBridgeProcess.test.ts index adae6c3a02..be1a913a44 100644 --- a/packages/protocol/test/bridge/libs/LibBridgeProcess.test.ts +++ b/packages/protocol/test/bridge/libs/LibBridgeProcess.test.ts @@ -106,7 +106,7 @@ describe("LibBridgeProcess", async function () { }; await expect( libProcess.processMessage(message, ethers.constants.HashZero) - ).to.be.revertedWith("B:forbidden"); + ).to.be.revertedWith("B_FORBIDDEN()"); }); it("should throw if message.destChain != block.chainId", async function () { @@ -128,7 +128,7 @@ describe("LibBridgeProcess", async function () { }; await expect( libProcess.processMessage(message, ethers.constants.HashZero) - ).to.be.revertedWith("B:destChainId"); + ).to.be.revertedWith("B_WRONG_CHAIN_ID()"); }); it("should throw if message's status is not NEW", async function () { @@ -158,7 +158,7 @@ describe("LibBridgeProcess", async function () { await expect( libProcess.processMessage(message, ethers.constants.HashZero) - ).to.be.revertedWith("B:status"); + ).to.be.revertedWith("B_STATUS_MISMTACH()"); }); // Remaining test cases require integration, will be covered in Bridge.test.ts }); diff --git a/packages/protocol/test/bridge/libs/LibBridgeRetry.test.ts b/packages/protocol/test/bridge/libs/LibBridgeRetry.test.ts index dbad717a3a..592818c4d7 100644 --- a/packages/protocol/test/bridge/libs/LibBridgeRetry.test.ts +++ b/packages/protocol/test/bridge/libs/LibBridgeRetry.test.ts @@ -120,7 +120,7 @@ describe("LibBridgeRetry", function () { await expect( libRetry.retryMessage(message, false) - ).to.be.revertedWith("B:denied"); + ).to.be.revertedWith("B_DENIED()"); }); it("should throw if lastAttempt == true && msg.sender != message.owner", async function () { @@ -142,7 +142,7 @@ describe("LibBridgeRetry", function () { await expect( libRetry.retryMessage(message, true) - ).to.be.revertedWith("B:denied"); + ).to.be.revertedWith("B_DENIED()"); }); it("should throw if message status is not RETRIABLE", async function () { @@ -164,7 +164,7 @@ describe("LibBridgeRetry", function () { await expect( libRetry.retryMessage(message, false) - ).to.be.revertedWith("B:notFound"); + ).to.be.revertedWith("B_MSG_NON_RETRIABLE()"); }); it("if etherVault resolves to address(0), retry should fail and messageStatus should not change if not lastAttempt since no ether received", async function () { diff --git a/packages/protocol/test/bridge/libs/LibBridgeSend.test.ts b/packages/protocol/test/bridge/libs/LibBridgeSend.test.ts index ca5d51a711..faf0d4a29c 100644 --- a/packages/protocol/test/bridge/libs/LibBridgeSend.test.ts +++ b/packages/protocol/test/bridge/libs/LibBridgeSend.test.ts @@ -82,7 +82,7 @@ describe("LibBridgeSend", function () { }; await expect(libSend.sendMessage(message)).to.be.revertedWith( - "B:owner" + "B_OWNER_IS_NULL()" ); }); @@ -104,7 +104,7 @@ describe("LibBridgeSend", function () { }; await expect(libSend.sendMessage(message)).to.be.revertedWith( - "B:destChainId" + "B_WRONG_CHAIN_ID()" ); }); @@ -128,7 +128,7 @@ describe("LibBridgeSend", function () { }; await expect(libSend.sendMessage(message)).to.be.revertedWith( - "B:destChainId" + "B_WRONG_CHAIN_ID()" ); }); @@ -150,7 +150,7 @@ describe("LibBridgeSend", function () { }; await expect(libSend.sendMessage(message)).to.be.revertedWith( - "B:value" + "B_INCORRECT_VALUE()" ); }); diff --git a/packages/protocol/test/etherVault/EtherVault.test.ts b/packages/protocol/test/etherVault/EtherVault.test.ts index e83806c7c9..b57c2562e4 100644 --- a/packages/protocol/test/etherVault/EtherVault.test.ts +++ b/packages/protocol/test/etherVault/EtherVault.test.ts @@ -52,7 +52,7 @@ describe("EtherVault", function () { to: etherVault.address, value: ethers.utils.parseEther("1.0"), }) - ).to.be.revertedWith("EV:denied"); + ).to.be.revertedWith("B_EV_NOT_AUTHORIZED()"); }); it("receives if authorized and balance > 0", async () => { @@ -88,7 +88,7 @@ describe("EtherVault", function () { it("throws if not authorized", async () => { await expect( etherVault.connect(notAuthorized)["releaseEther(uint256)"](1) - ).to.be.revertedWith("EV:denied"); + ).to.be.revertedWith("B_EV_NOT_AUTHORIZED()"); }); it("sends ether to caller", async () => { @@ -138,13 +138,13 @@ describe("EtherVault", function () { etherVault .connect(owner) .authorize(ethers.constants.AddressZero, true) - ).to.be.revertedWith("EV:param"); + ).to.be.revertedWith("B_EV_PARAM()"); }); it("throws when authorized state is the same as input", async () => { await expect( etherVault.connect(owner).authorize(authorized.address, true) - ).to.be.revertedWith("EV:param"); + ).to.be.revertedWith("B_EV_PARAM()"); }); it("emits Authorized event upon success", async () => { diff --git a/packages/protocol/test/genesis/generate_genesis.test.ts b/packages/protocol/test/genesis/generate_genesis.test.ts index 7294d252a5..654f33335e 100644 --- a/packages/protocol/test/genesis/generate_genesis.test.ts +++ b/packages/protocol/test/genesis/generate_genesis.test.ts @@ -252,8 +252,8 @@ action("Generate Genesis", function () { expect(owner).to.be.equal(testConfig.contractOwner); - await expect( - Bridge.processMessage( + const txPromise = ( + await Bridge.processMessage( { id: 0, sender: ethers.Wallet.createRandom().address, @@ -269,9 +269,18 @@ action("Generate Genesis", function () { data: ethers.utils.randomBytes(1024), memo: "", }, - ethers.utils.randomBytes(1024) + ethers.utils.randomBytes(1024), + { + gasLimit: 5000000, + } ) - ).to.be.revertedWith("B:forbidden"); + ).wait(1); + + await txShouldRevertWithCustomError( + txPromise, + provider, + "B_FORBIDDEN()" + ); }); it("TokenVault", async function () { diff --git a/packages/protocol/test/signal/SignalService.integration.test.ts b/packages/protocol/test/signal/SignalService.integration.test.ts index 39a1325ed4..94e81e1b0e 100644 --- a/packages/protocol/test/signal/SignalService.integration.test.ts +++ b/packages/protocol/test/signal/SignalService.integration.test.ts @@ -112,7 +112,7 @@ describe("integration:SignalService", function () { signal, signalProof ) - ).to.be.revertedWith("B:srcChainId"); + ).to.be.revertedWith("B_WRONG_CHAIN_ID()"); }); it("should revert if app == AddressZero", async function () { @@ -151,7 +151,7 @@ describe("integration:SignalService", function () { signal, signalProof ) - ).to.be.revertedWith("B:app"); + ).to.be.revertedWith("B_NULL_APP_ADDR()"); }); it("should revert if signal == HashZero", async function () { @@ -190,7 +190,7 @@ describe("integration:SignalService", function () { ethers.constants.HashZero, signalProof ) - ).to.be.revertedWith("B:signal"); + ).to.be.revertedWith("B_ZERO_SIGNAL()"); }); it("should pass and return true", async function () {