Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audit-202409 #24

Merged
merged 16 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions contracts/ILCPClientErrors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ interface ILCPClientErrors {
error LCPClientUpdateStateEmittedStatesMustNotEmpty();
error LCPClientUpdateStatePrevStateIdMustNotEmpty();
error LCPClientUpdateStateUnexpectedPrevStateId();
error LCPClientUpdateStateInconsistentConsensusState();

error LCPClientMisbehaviourPrevStatesMustNotEmpty();

Expand Down
19 changes: 13 additions & 6 deletions contracts/LCPClientBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ abstract contract LCPClientBase is ILightClient, ILCPClientErrors {
/**
* @dev initializeClient initializes a new client with the given state.
* If succeeded, it returns heights at which the consensus state are stored.
* The function must be only called by IBCHandler.
* This function is guaranteed by the IBC contract to be called only once for each `clientId`.
* @param clientId the client identifier which is unique within the IBC handler
*/
function initializeClient(
string calldata clientId,
Expand Down Expand Up @@ -433,16 +434,22 @@ abstract contract LCPClientBase is ILightClient, ILCPClientErrors {

LCPCommitment.validationContextEval(pmsg.context, block.timestamp * 1e9);

uint128 latestHeight = clientState.latest_height.toUint128();
uint128 postHeight = pmsg.postHeight.toUint128();
if (latestHeight < postHeight) {
clientState.latest_height = pmsg.postHeight;
}

consensusState = clientStorage.consensusStates[postHeight];
if (consensusState.stateId != bytes32(0)) {
if (consensusState.stateId != pmsg.postStateId || consensusState.timestamp != uint64(pmsg.timestamp)) {
revert LCPClientUpdateStateInconsistentConsensusState();
}
// return empty heights if the consensus state is already stored
return heights;
}
consensusState.stateId = pmsg.postStateId;
consensusState.timestamp = uint64(pmsg.timestamp);

uint128 latestHeight = clientState.latest_height.toUint128();
if (latestHeight < postHeight) {
clientState.latest_height = pmsg.postHeight;
}
heights = new Height.Data[](1);
heights[0] = pmsg.postHeight;
return heights;
Expand Down
13 changes: 13 additions & 0 deletions test/LCPClientTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,26 @@ contract LCPClientTest is BasicTest {
}

TestData[] memory dataList = readTestDataList(commandStartNumber);
bool firstUpdate = true;
for (uint256 i = 0; i < dataList.length; i++) {
if (dataList[i].cmd == Command.UpdateClient) {
UpdateClientMessage.Data memory message = createUpdateClientMessage(dataList[i].path);
Height.Data[] memory heights = lc.updateClient(clientId, message);
require(heights.length == 1, "heights length must be 1");
console.log("revision_height:");
console.log(heights[0].revision_height);
if (firstUpdate) {
firstUpdate = false;
} else {
// repeat updateClient to check the state is not changed
message = createUpdateClientMessage(dataList[i].path);
// staticcall is expected to succeed because updateClient does not update the state if the message is already processed
(bool success, bytes memory ret) = address(lc).staticcall(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should check if success is true here.
Fixed at 86e5a24

abi.encodeWithSelector(LCPClientBase.updateClient.selector, clientId, message)
);
heights = abi.decode(ret, (Height.Data[]));
require(heights.length == 0, "heights length must be 0");
}
} else if (dataList[i].cmd == Command.VerifyMembership) {
(
Height.Data memory height,
Expand Down