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

Remove channel id array #1

Merged
merged 2 commits into from
Feb 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
- name: Static analysis
run: |
pip3 install slither-analyzer==0.10.4
slither --exclude solc-version,timestamp,boolean-equality,unimplemented-functions,locked-ether --filter-paths vendor/ .
slither --exclude solc-version,timestamp,boolean-equality,unimplemented-functions,locked-ether,immutable-states --filter-paths vendor/ .
# Alternatively, one can use Docker:
# WORKDIR=/share docker run --rm -v $(pwd):$WORKDIR -w $WORKDIR --entrypoint slither trailofbits/eth-security-toolbox [insert slither parameters here]

Expand Down
52 changes: 14 additions & 38 deletions contracts/Adjudicator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
pragma solidity ^0.8.15;
pragma abicoder v2;

import "./Channel.sol";

Check warning on line 20 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

global import of path ./Channel.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

Check warning on line 20 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

global import of path ./Channel.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)
import "./App.sol";

Check warning on line 21 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

global import of path ./App.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

Check warning on line 21 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

global import of path ./App.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)
import "./AssetHolder.sol";

Check warning on line 22 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

global import of path ./AssetHolder.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

Check warning on line 22 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

global import of path ./AssetHolder.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)
import "./Array.sol";

Check warning on line 23 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

global import of path ./Array.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

Check warning on line 23 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

global import of path ./Array.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

/**
* @title The Perun Adjudicator
Expand Down Expand Up @@ -85,7 +85,7 @@
SignedState memory channel,
SignedState[] memory subChannels
) external {
require(channel.params.ledgerChannel, "not ledger");

Check warning on line 88 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

GC: Use Custom Errors instead of require statements

Check warning on line 88 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

GC: Use Custom Errors instead of require statements
registerRecursive(channel, subChannels, 0);
}

Expand All @@ -101,8 +101,8 @@
function registerRecursive(
SignedState memory channel,
SignedState[] memory subChannels,
uint startIndex

Check warning on line 104 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

Rule is set with explicit type [var/s: uint]

Check warning on line 104 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

Rule is set with explicit type [var/s: uint]
) internal returns (uint256[] memory outcome, uint nextIndex) {

Check warning on line 105 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

Rule is set with explicit type [var/s: uint]

Check warning on line 105 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

Rule is set with explicit type [var/s: uint]
nextIndex = startIndex;
Channel.Allocation memory alloc = channel.state.outcome;
Channel.Asset[] memory assets = alloc.assets;
Expand All @@ -114,14 +114,14 @@
// For each sub-channel, register recursively and check the accumulated
// outcome against the locked assets.
Channel.SubAlloc[] memory locked = alloc.locked;
require(locked.length <= subChannels.length, "subChannels too short");

Check warning on line 117 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

GC: Use Custom Errors instead of require statements

Check warning on line 117 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

GC: Use Custom Errors instead of require statements
for (uint s = 0; s < locked.length; ++s) {

Check warning on line 118 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

Rule is set with explicit type [var/s: uint]

Check warning on line 118 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

Rule is set with explicit type [var/s: uint]
SignedState memory _channel = subChannels[nextIndex++];
(Channel.SubAlloc memory subAlloc, Channel.State memory _state) = (
locked[s],
_channel.state
);
require(Channel.areBytes32ArraysEqual(subAlloc.ID, _state.channelID), "invalid sub-channel id");
require(subAlloc.ID == _state.channelID, "invalid sub-channel id");

Check warning on line 124 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

GC: Use Custom Errors instead of require statements

Check warning on line 124 in contracts/Adjudicator.sol

View workflow job for this annotation

GitHub Actions / Build & Test

GC: Use Custom Errors instead of require statements

uint256[] memory _outcome;
(_outcome, nextIndex) = registerRecursive(
Expand Down Expand Up @@ -159,10 +159,7 @@
}

// If registered, require newer version and refutation timeout not passed.
(Dispute memory dispute, bool registered) = getDispute(state.channelID[Channel.findBackendIndex(
state.channelID,
state.outcome.backends
)]);
(Dispute memory dispute, bool registered) = getDispute(state.channelID);
if (registered) {
if (dispute.stateHash == hashState(state)) {
// Skip if same state.
Expand Down Expand Up @@ -206,10 +203,7 @@
uint256 actorIdx,
bytes memory sig
) external {
Dispute storage dispute = requireGetDispute(state.channelID[Channel.findBackendIndex(
state.channelID,
state.outcome.backends
)]);
Dispute storage dispute = requireGetDispute(state.channelID);
if (dispute.phase == uint8(DisputePhase.DISPUTE)) {
// solhint-disable-next-line not-rely-on-time
require(block.timestamp >= dispute.timeout, "timeout not passed");
Expand Down Expand Up @@ -292,10 +286,7 @@
Channel.validateSignatures(params, state, sigs);

// If registered, require not concluded.
(Dispute storage dispute, bool registered) = getDispute(state.channelID[Channel.findBackendIndex(
state.channelID,
state.outcome.backends
)]);
(Dispute storage dispute, bool registered) = getDispute(state.channelID);
if (registered) {
require(
dispute.phase != uint8(DisputePhase.CONCLUDED),
Expand Down Expand Up @@ -343,10 +334,7 @@
Channel.Params memory params,
Channel.State memory state
) internal pure {
require(state.channelID[Channel.findBackendIndex(
state.channelID,
state.outcome.backends
)] == channelID(params), "invalid params");
require(state.channelID == channelID(params), "invalid params");
}

/**
Expand All @@ -361,11 +349,7 @@
Channel.State memory state,
DisputePhase disputePhase
) internal {
uint256 zeroIndex = Channel.findBackendIndex(
state.channelID,
state.outcome.backends
);
(Dispute storage dispute, bool registered) = getDispute(state.channelID[zeroIndex]);
(Dispute storage dispute, bool registered) = getDispute(state.channelID);

dispute.challengeDuration = uint64(params.challengeDuration);
dispute.version = state.version;
Expand All @@ -386,7 +370,7 @@
dispute.timeout = uint64(block.timestamp) + dispute.challengeDuration;
}

setDispute(state.channelID[zeroIndex], dispute);
setDispute(state.channelID, dispute);
}

/**
Expand Down Expand Up @@ -465,11 +449,7 @@
* Reverts if the channel is already concluded.
*/
function concludeSingle(Channel.State memory state) internal {
uint64 zeroIndex = Channel.findBackendIndex(
state.channelID,
state.outcome.backends
);
Dispute storage dispute = requireGetDispute(state.channelID[zeroIndex]);
Dispute storage dispute = requireGetDispute(state.channelID);
require(dispute.stateHash == hashState(state), "invalid state");
require(
dispute.phase != uint8(DisputePhase.CONCLUDED),
Expand All @@ -485,7 +465,7 @@
require(block.timestamp >= dispute.timeout, "timeout not passed yet");
dispute.phase = uint8(DisputePhase.CONCLUDED);

setDispute(state.channelID[zeroIndex], dispute);
setDispute(state.channelID, dispute);
}

/**
Expand Down Expand Up @@ -520,7 +500,7 @@
for (uint256 i = 0; i < locked.length; ++i) {
Channel.SubAlloc memory subAlloc = locked[i];
Channel.State memory subState = subStates[nextIndex++];
require(Channel.areBytes32ArraysEqual(subAlloc.ID, subState.channelID), "invalid subchannel id");
require(subAlloc.ID == subState.channelID, "invalid subchannel id");

uint256[][] memory subOutcome;
(subOutcome, nextIndex) = forceConcludeRecursive(
Expand All @@ -546,23 +526,19 @@
* Reverts if the channel is not registered.
*/
function forceConcludeSingle(Channel.State memory state) internal {
uint64 zeroIndex = Channel.findBackendIndex(
state.channelID,
state.outcome.backends
);
Dispute storage dispute = requireGetDispute(state.channelID[zeroIndex]);
Dispute storage dispute = requireGetDispute(state.channelID);
require(dispute.stateHash == hashState(state), "invalid state");
if (dispute.phase != uint8(DisputePhase.CONCLUDED)) {
dispute.phase = uint8(DisputePhase.CONCLUDED);
setDispute(state.channelID[zeroIndex], dispute);
setDispute(state.channelID, dispute);
}
}

/**
* @dev pushOutcome sets the outcome at the asset holders.
*/
function pushOutcome(
bytes32[] memory channel,
bytes32 channel,
Channel.Asset[] memory assets,
Channel.Participant[] memory participants,
uint256[][] memory outcome
Expand All @@ -573,7 +549,7 @@
if (asset.ethHolder != address(0)) {
// solhint-disable-next-line calls-loop
AssetHolder(asset.ethHolder).setOutcome(
channel[a],
channel,
participants,
outcome[a]
);
Expand Down
2 changes: 1 addition & 1 deletion contracts/AssetHolder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ abstract contract AssetHolder {
* @notice Address of the adjudicator contract that can call setOutcome.
* @dev Set by the constructor.
*/
address public immutable adjudicator;
address public adjudicator;

/**
* @notice The onlyAdjudicator modifier specifies functions that can only be called from the adjudicator contract.
Expand Down
33 changes: 3 additions & 30 deletions contracts/Channel.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ library Channel {
}

struct State {
bytes32[] channelID;
bytes32 channelID;
uint64 version;
Allocation outcome;
bytes appData;
Expand All @@ -59,7 +59,7 @@ library Channel {

struct SubAlloc {
// ID is the channelID of the subchannel
bytes32[] ID; // solhint-disable-line var-name-mixedcase
bytes32 ID; // solhint-disable-line var-name-mixedcase
// balances holds the total balance of the subchannel of every asset.
uint256[] balances;
// indexMap maps each sub-channel participant to a parent channel
Expand Down Expand Up @@ -125,38 +125,11 @@ library Channel {
SubAlloc memory a,
SubAlloc memory b
) internal pure {
require(areBytes32ArraysEqual(a.ID, b.ID), "SubAlloc: unequal ID");
require(a.ID == b.ID, "SubAlloc: unequal ID");
Array.requireEqualUint256Array(a.balances, b.balances);
Array.requireEqualUint16Array(a.indexMap, b.indexMap);
}

// @dev areBytes32ArraysEqual checks if two arrays of bytes32 are equal.
function areBytes32ArraysEqual(bytes32[] memory arr1, bytes32[] memory arr2) internal pure returns (bool) {
if (arr1.length != arr2.length) {
return false;
}
for (uint i = 0; i < arr1.length; ++i) {
if (arr1[i] != arr2[i]) {
return false;
}
}
return true;
}

/**
* @dev findBackendIndex finds out which of the channelIDs corresponds to the ethereum encoded channelID.
* Reverts if none of the channelIDs has a zero backend.
* Optimized for the common case of only one zero backend.
*/
function findBackendIndex(bytes32[] memory channel, uint256[] memory backends) internal pure returns (uint64) {
require(channel.length == backends.length, "Array lengths mismatch");

if (backends[0] == 1) return 0;
if (backends.length > 1 && backends[1] == 1) return 1;

return 0;
}

/// @dev Asserts that a and b are equal.
function requireEqualAsset(Asset memory a, Asset memory b) internal pure {
require(a.chainID == b.chainID, "unequal chainID");
Expand Down
6 changes: 0 additions & 6 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,6 @@ import "solidity-coverage";
const config: HardhatUserConfig = {
solidity: {
version: "0.8.28",
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
};

Expand Down
Loading
Loading