Skip to content

Commit

Permalink
refactor: using require instead of revert where possible (#107)
Browse files Browse the repository at this point in the history
  • Loading branch information
srdtrk authored Nov 18, 2024
1 parent 2de017c commit e638755
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 193 deletions.
2 changes: 0 additions & 2 deletions .github/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ runs:
uses: "actions/checkout@v4"
- name: "Install Foundry"
uses: "foundry-rs/foundry-toolchain@v1"
with:
version: nightly-f8aa4afec04cc0b7d364a5d78f0cde9e64fd14bf
- name: "Install Bun"
uses: "oven-sh/setup-bun@v2"
- name: "Install the Node.js dependencies"
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/foundry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,10 @@ jobs:
uses: ./.github/setup

- name: "Run coverage"
run: "bash scripts/checks/coverage.sh"
run: forge coverage --report lcov

- uses: codecov/codecov-action@v4
with:
exclude: test
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
3 changes: 2 additions & 1 deletion .solhint.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"named-parameters-mapping": "warn",
"no-console": "off",
"not-rely-on-time": "off",
"one-contract-per-file": "off"
"one-contract-per-file": "off",
"gas-custom-errors": "off"
}
}
2 changes: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
block_timestamp = 1_680_220_800 # March 31, 2023 at 00:00 GMT
bytecode_hash = "none"
evm_version = "cancun"
fuzz = { runs = 1_000_00 }
fuzz = { runs = 100_000 }
gas_reports = ["*"]
optimizer = true
optimizer_runs = 10_000
Expand Down
2 changes: 1 addition & 1 deletion scripts/E2ETestDeploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pragma solidity ^0.8.28;
This script is used for end-to-end testing with SP1_PROVER=network.
*/

// solhint-disable gas-custom-errors,custom-errors
// solhint-disable custom-errors

import { stdJson } from "forge-std/StdJson.sol";
import { Script } from "forge-std/Script.sol";
Expand Down
10 changes: 0 additions & 10 deletions scripts/checks/coverage.sh

This file was deleted.

12 changes: 3 additions & 9 deletions src/ICS02Client.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ contract ICS02Client is IICS02Client, IICS02ClientErrors, Ownable {
/// @param clientType The client type
/// @return The next client identifier
function getNextClientId(string calldata clientType) private returns (string memory) {
if (!IBCIdentifiers.validateClientType(clientType)) {
revert IBCInvalidClientType(clientType);
}
require(IBCIdentifiers.validateClientType(clientType), IBCInvalidClientType(clientType));

uint32 seq = nextClientSeq[clientType];
nextClientSeq[clientType] = seq + 1;
Expand All @@ -35,19 +33,15 @@ contract ICS02Client is IICS02Client, IICS02ClientErrors, Ownable {
/// @inheritdoc IICS02Client
function getCounterparty(string calldata clientId) public view returns (CounterpartyInfo memory) {
CounterpartyInfo memory counterpartyInfo = counterpartyInfos[clientId];
if (bytes(counterpartyInfo.clientId).length == 0) {
revert IBCCounterpartyClientNotFound(clientId);
}
require(bytes(counterpartyInfo.clientId).length != 0, IBCCounterpartyClientNotFound(clientId));

return counterpartyInfo;
}

/// @inheritdoc IICS02Client
function getClient(string calldata clientId) public view returns (ILightClient) {
ILightClient client = clients[clientId];
if (client == ILightClient(address(0))) {
revert IBCClientNotFound(clientId);
}
require(address(client) != address(0), IBCClientNotFound(clientId));

return client;
}
Expand Down
31 changes: 12 additions & 19 deletions src/ICS20Transfer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,7 @@ contract ICS20Transfer is IIBCApp, IICS20Transfer, IICS20Errors, Ownable, Reentr

/// @inheritdoc IICS20Transfer
function sendTransfer(SendTransferMsg calldata msg_) external override returns (uint32) {
if (msg_.amount == 0) {
revert ICS20InvalidAmount(msg_.amount);
}
require(msg_.amount > 0, ICS20InvalidAmount(msg_.amount));

// we expect the denom to be an erc20 address
address contractAddress = ICS20Lib.mustHexStringToAddress(msg_.denom);
Expand Down Expand Up @@ -83,19 +81,16 @@ contract ICS20Transfer is IIBCApp, IICS20Transfer, IICS20Errors, Ownable, Reentr
// The packet sender has to be the contract itself.
// Because of the packetData massaging we do in sendTransfer to convert the amount to sdkCoin, we don't allow
// this function to be called by anyone else. They could end up transferring a larger amount than intended.
if (msg_.sender != address(this)) {
revert ICS20UnauthorizedPacketSender(msg_.sender);
}
require(msg_.sender == address(this), ICS20UnauthorizedPacketSender(msg_.sender));

if (keccak256(bytes(msg_.payload.version)) != keccak256(bytes(ICS20Lib.ICS20_VERSION))) {
revert ICS20UnexpectedVersion(ICS20Lib.ICS20_VERSION, msg_.payload.version);
}
require(
keccak256(bytes(msg_.payload.version)) == keccak256(bytes(ICS20Lib.ICS20_VERSION)),
ICS20UnexpectedVersion(ICS20Lib.ICS20_VERSION, msg_.payload.version)
);

ICS20Lib.PacketDataJSON memory packetData = ICS20Lib.unmarshalJSON(msg_.payload.value);

if (packetData.amount == 0) {
revert ICS20InvalidAmount(packetData.amount);
}
require(packetData.amount > 0, ICS20InvalidAmount(packetData.amount));

address sender = ICS20Lib.mustHexStringToAddress(packetData.sender);

Expand Down Expand Up @@ -137,7 +132,6 @@ contract ICS20Transfer is IIBCApp, IICS20Transfer, IICS20Errors, Ownable, Reentr
return ICS20Lib.errorAck(abi.encodePacked("invalid receiver: ", packetData.receiver));
}

// TODO: Implement escrow balance tracking (#6)
if (originatorChainIsSource) {
// sender is source, so we mint vouchers
// NOTE: getReceiveTokenContractAndSource has already created a contract if it didn't exist
Expand Down Expand Up @@ -202,9 +196,10 @@ contract ICS20Transfer is IIBCApp, IICS20Transfer, IICS20Errors, Ownable, Reentr
uint256 expectedEndingBalance = ourStartingBalance + amount;
// a very strange ERC20 may trigger this condition, if we didn't have this we would
// underflow, so it's mostly just an error message printer
if (actualEndingBalance <= ourStartingBalance || actualEndingBalance != expectedEndingBalance) {
revert ICS20UnexpectedERC20Balance(expectedEndingBalance, actualEndingBalance);
}
require(
actualEndingBalance > ourStartingBalance && actualEndingBalance == expectedEndingBalance,
ICS20UnexpectedERC20Balance(expectedEndingBalance, actualEndingBalance)
);
}

/// @notice For a send packet, get the ERC20 address for the token and whether the originator chain is the source
Expand Down Expand Up @@ -234,9 +229,7 @@ contract ICS20Transfer is IIBCApp, IICS20Transfer, IICS20Errors, Ownable, Reentr
// receiving chain is source of the token, so we've received and mapped this token before
string memory ibcDenom = ICS20Lib.toIBCDenom(packetData.denom);
erc20Address = address(_ibcDenomContracts[ibcDenom]);
if (erc20Address == address(0)) {
revert ICS20DenomNotFound(packetData.denom);
}
require(erc20Address != address(0), ICS20DenomNotFound(packetData.denom));
}
return (erc20Address, originatorChainIsSource);
}
Expand Down
88 changes: 39 additions & 49 deletions src/ICS26Router.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,7 @@ contract ICS26Router is IICS26Router, IICS26RouterErrors, Ownable, ReentrancyGua
/// @inheritdoc IICS26Router
function getIBCApp(string calldata portId) public view returns (IIBCApp) {
IIBCApp app = apps[portId];
if (app == IIBCApp(address(0))) {
revert IBCAppNotFound(portId);
}
require(address(app) != address(0), IBCAppNotFound(portId));
return app;
}

Expand All @@ -59,12 +57,8 @@ contract ICS26Router is IICS26Router, IICS26RouterErrors, Ownable, ReentrancyGua
newPortId = Strings.toHexString(app);
}

if (apps[newPortId] != IIBCApp(address(0))) {
revert IBCPortAlreadyExists(newPortId);
}
if (!IBCIdentifiers.validatePortIdentifier(bytes(newPortId))) {
revert IBCInvalidPortIdentifier(newPortId);
}
require(address(apps[newPortId]) == address(0), IBCPortAlreadyExists(newPortId));
require(IBCIdentifiers.validatePortIdentifier(bytes(newPortId)), IBCInvalidPortIdentifier(newPortId));

apps[newPortId] = IIBCApp(app);

Expand All @@ -77,17 +71,15 @@ contract ICS26Router is IICS26Router, IICS26RouterErrors, Ownable, ReentrancyGua
/// @inheritdoc IICS26Router
function sendPacket(MsgSendPacket calldata msg_) external nonReentrant returns (uint32) {
// TODO: Support multi-payload packets #93
if (msg_.payloads.length != 1) {
revert IBCMultiPayloadPacketNotSupported();
}
require(msg_.payloads.length == 1, IBCMultiPayloadPacketNotSupported());
Payload calldata payload = msg_.payloads[0];

string memory counterpartyId = ICS02_CLIENT.getCounterparty(msg_.sourceChannel).clientId;

// TODO: validate all identifiers
if (msg_.timeoutTimestamp <= block.timestamp) {
revert IBCInvalidTimeoutTimestamp(msg_.timeoutTimestamp, block.timestamp);
}
require(
msg_.timeoutTimestamp > block.timestamp, IBCInvalidTimeoutTimestamp(msg_.timeoutTimestamp, block.timestamp)
);

uint32 sequence = IBC_STORE.nextSequenceSend(msg_.sourceChannel);

Expand Down Expand Up @@ -120,19 +112,18 @@ contract ICS26Router is IICS26Router, IICS26RouterErrors, Ownable, ReentrancyGua
/// @inheritdoc IICS26Router
function recvPacket(MsgRecvPacket calldata msg_) external nonReentrant {
// TODO: Support multi-payload packets #93
if (msg_.packet.payloads.length != 1) {
revert IBCMultiPayloadPacketNotSupported();
}
require(msg_.packet.payloads.length == 1, IBCMultiPayloadPacketNotSupported());
Payload calldata payload = msg_.packet.payloads[0];

IICS02ClientMsgs.CounterpartyInfo memory cInfo = ICS02_CLIENT.getCounterparty(msg_.packet.destChannel);
if (keccak256(bytes(cInfo.clientId)) != keccak256(bytes(msg_.packet.sourceChannel))) {
revert IBCInvalidCounterparty(cInfo.clientId, msg_.packet.sourceChannel);
}

if (msg_.packet.timeoutTimestamp <= block.timestamp) {
revert IBCInvalidTimeoutTimestamp(msg_.packet.timeoutTimestamp, block.timestamp);
}
require(
keccak256(bytes(cInfo.clientId)) == keccak256(bytes(msg_.packet.sourceChannel)),
IBCInvalidCounterparty(cInfo.clientId, msg_.packet.sourceChannel)
);
require(
msg_.packet.timeoutTimestamp > block.timestamp,
IBCInvalidTimeoutTimestamp(msg_.packet.timeoutTimestamp, block.timestamp)
);

bytes memory commitmentPath =
ICS24Host.packetCommitmentPathCalldata(msg_.packet.sourceChannel, msg_.packet.sequence);
Expand All @@ -157,9 +148,7 @@ contract ICS26Router is IICS26Router, IICS26RouterErrors, Ownable, ReentrancyGua
relayer: _msgSender()
})
);
if (acks[0].length == 0) {
revert IBCAsyncAcknowledgementNotSupported();
}
require(acks[0].length != 0, IBCAsyncAcknowledgementNotSupported());

writeAcknowledgement(msg_.packet, acks);

Expand All @@ -173,21 +162,21 @@ contract ICS26Router is IICS26Router, IICS26RouterErrors, Ownable, ReentrancyGua
/// @inheritdoc IICS26Router
function ackPacket(MsgAckPacket calldata msg_) external nonReentrant {
// TODO: Support multi-payload packets #93
if (msg_.packet.payloads.length != 1) {
revert IBCMultiPayloadPacketNotSupported();
}
require(msg_.packet.payloads.length == 1, IBCMultiPayloadPacketNotSupported());
Payload calldata payload = msg_.packet.payloads[0];

IICS02ClientMsgs.CounterpartyInfo memory cInfo = ICS02_CLIENT.getCounterparty(msg_.packet.sourceChannel);
if (keccak256(bytes(cInfo.clientId)) != keccak256(bytes(msg_.packet.destChannel))) {
revert IBCInvalidCounterparty(cInfo.clientId, msg_.packet.destChannel);
}
require(
keccak256(bytes(cInfo.clientId)) == keccak256(bytes(msg_.packet.destChannel)),
IBCInvalidCounterparty(cInfo.clientId, msg_.packet.destChannel)
);

// this will revert if the packet commitment does not exist
bytes32 storedCommitment = IBC_STORE.deletePacketCommitment(msg_.packet);
if (storedCommitment != ICS24Host.packetCommitmentBytes32(msg_.packet)) {
revert IBCPacketCommitmentMismatch(storedCommitment, ICS24Host.packetCommitmentBytes32(msg_.packet));
}
require(
storedCommitment == ICS24Host.packetCommitmentBytes32(msg_.packet),
IBCPacketCommitmentMismatch(storedCommitment, ICS24Host.packetCommitmentBytes32(msg_.packet))
);

bytes memory commitmentPath =
ICS24Host.packetAcknowledgementCommitmentPathCalldata(msg_.packet.destChannel, msg_.packet.sequence);
Expand Down Expand Up @@ -224,21 +213,21 @@ contract ICS26Router is IICS26Router, IICS26RouterErrors, Ownable, ReentrancyGua
/// @inheritdoc IICS26Router
function timeoutPacket(MsgTimeoutPacket calldata msg_) external nonReentrant {
// TODO: Support multi-payload packets #93
if (msg_.packet.payloads.length != 1) {
revert IBCMultiPayloadPacketNotSupported();
}
require(msg_.packet.payloads.length == 1, IBCMultiPayloadPacketNotSupported());
Payload calldata payload = msg_.packet.payloads[0];

IICS02ClientMsgs.CounterpartyInfo memory cInfo = ICS02_CLIENT.getCounterparty(msg_.packet.sourceChannel);
if (keccak256(bytes(cInfo.clientId)) != keccak256(bytes(msg_.packet.destChannel))) {
revert IBCInvalidCounterparty(cInfo.clientId, msg_.packet.destChannel);
}
require(
keccak256(bytes(cInfo.clientId)) == keccak256(bytes(msg_.packet.destChannel)),
IBCInvalidCounterparty(cInfo.clientId, msg_.packet.destChannel)
);

// this will revert if the packet commitment does not exist
bytes32 storedCommitment = IBC_STORE.deletePacketCommitment(msg_.packet);
if (storedCommitment != ICS24Host.packetCommitmentBytes32(msg_.packet)) {
revert IBCPacketCommitmentMismatch(storedCommitment, ICS24Host.packetCommitmentBytes32(msg_.packet));
}
require(
storedCommitment == ICS24Host.packetCommitmentBytes32(msg_.packet),
IBCPacketCommitmentMismatch(storedCommitment, ICS24Host.packetCommitmentBytes32(msg_.packet))
);

bytes memory receiptPath =
ICS24Host.packetReceiptCommitmentPathCalldata(msg_.packet.destChannel, msg_.packet.sequence);
Expand All @@ -250,9 +239,10 @@ contract ICS26Router is IICS26Router, IICS26RouterErrors, Ownable, ReentrancyGua
});

uint256 counterpartyTimestamp = ICS02_CLIENT.getClient(msg_.packet.sourceChannel).membership(nonMembershipMsg);
if (counterpartyTimestamp < msg_.packet.timeoutTimestamp) {
revert IBCInvalidTimeoutTimestamp(msg_.packet.timeoutTimestamp, counterpartyTimestamp);
}
require(
counterpartyTimestamp >= msg_.packet.timeoutTimestamp,
IBCInvalidTimeoutTimestamp(msg_.packet.timeoutTimestamp, counterpartyTimestamp)
);

getIBCApp(payload.sourcePort).onTimeoutPacket(
IIBCAppCallbacks.OnTimeoutPacketCallback({
Expand Down
38 changes: 20 additions & 18 deletions src/utils/IBCStore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,26 @@ contract IBCStore is IIBCStore, IICS24HostErrors, Ownable {
/// @inheritdoc IIBCStore
function commitPacket(IICS26RouterMsgs.Packet memory packet) public onlyOwner {
bytes32 path = ICS24Host.packetCommitmentKeyCalldata(packet.sourceChannel, packet.sequence);
if (commitments[path] != 0) {
revert IBCPacketCommitmentAlreadyExists(
require(
commitments[path] == 0,
IBCPacketCommitmentAlreadyExists(
ICS24Host.packetCommitmentPathCalldata(packet.sourceChannel, packet.sequence)
);
}
)
);

bytes32 commitment = ICS24Host.packetCommitmentBytes32(packet);
emit PacketCommitted(path, commitment);
commitments[path] = commitment;
emit PacketCommitted(path, commitment);
}

/// @inheritdoc IIBCStore
function deletePacketCommitment(IICS26RouterMsgs.Packet memory packet) public onlyOwner returns (bytes32) {
bytes32 path = ICS24Host.packetCommitmentKeyCalldata(packet.sourceChannel, packet.sequence);
bytes32 commitment = commitments[path];
if (commitment == 0) {
revert IBCPacketCommitmentNotFound(
ICS24Host.packetCommitmentPathCalldata(packet.sourceChannel, packet.sequence)
);
}
require(
commitment != 0,
IBCPacketCommitmentNotFound(ICS24Host.packetCommitmentPathCalldata(packet.sourceChannel, packet.sequence))
);

delete commitments[path];
return commitment;
Expand All @@ -63,23 +63,25 @@ contract IBCStore is IIBCStore, IICS24HostErrors, Ownable {
/// @inheritdoc IIBCStore
function setPacketReceipt(IICS26RouterMsgs.Packet memory packet) public onlyOwner {
bytes32 path = ICS24Host.packetReceiptCommitmentKeyCalldata(packet.destChannel, packet.sequence);
if (commitments[path] != 0) {
revert IBCPacketReceiptAlreadyExists(
require(
commitments[path] == 0,
IBCPacketReceiptAlreadyExists(
ICS24Host.packetReceiptCommitmentPathCalldata(packet.destChannel, packet.sequence)
);
}
)
);

commitments[path] = ICS24Host.PACKET_RECEIPT_SUCCESSFUL_KECCAK256;
}

/// @inheritdoc IIBCStore
function commitPacketAcknowledgement(IICS26RouterMsgs.Packet memory packet, bytes[] memory acks) public onlyOwner {
bytes32 path = ICS24Host.packetAcknowledgementCommitmentKeyCalldata(packet.destChannel, packet.sequence);
if (commitments[path] != 0) {
revert IBCPacketAcknowledgementAlreadyExists(
require(
commitments[path] == 0,
IBCPacketAcknowledgementAlreadyExists(
ICS24Host.packetAcknowledgementCommitmentPathCalldata(packet.destChannel, packet.sequence)
);
}
)
);

bytes32 commitment = ICS24Host.packetAcknowledgementCommitmentBytes32(acks);
emit AckCommitted(path, commitment);
Expand Down
Loading

0 comments on commit e638755

Please sign in to comment.