xanoutas/solidity-security-findings huggingface dataset:
Upgraded Q -> 3 from #553 [1730391000655]
Audit: 2024-08-chakra-findings
Severity: HIGH

Judge has assessed an item in Issue #553 as 3 risk. The relevant finding follows:

 ## [QA-18] Cross-chain txs always revert in case are invalid, instead of setting status = `FAILED`

**Issue Description:**

There are `else` clauses in Cairo contracts that are unreachable because all calls before them always return the same value, and the `else` will never be entered.

The first case is in `receive_cross_chain_msg`. A call made to `handler.receive_cross_chain_msg` will always return `true`, not allowing the `Status` to be `Failed`, since all cases that result in a cross-chain tx to fail are strictly asserted in the handler, and this else will never be reached.

[settlement.cairo#L387-L396](https://github.com/code-423n4/2024-08-chakra/blob/d0d45ae1d26ca1b87034e67180fac07ce9642fd9/cairo/handler/src/settlement.cairo#L356-L361)

```rust
fn receive_cross_chain_msg(
    ref self: ContractState,
    cross_chain_msg_id: u256,       
    from_chain: felt252,
    to_chain: felt252,
    from_handler: u256,
    to_handler: ContractAddress,
    sign_type: u8,
    signatures: Array<(felt252, felt252, bool)>,
    payload: Array<u8>,
    payload_type: u8,
) -> bool {
    ...
    

    // call handler receive_cross_chain_msg
    let handler = IHandlerDispatcher{contract_address: to_handler};
    let success = handler.receive_cross_chain_msg(cross_chain_msg_id, from_chain, to_chain, from_handler, to_handler , payload);

    let mut status = CrossChainMsgStatus::SUCCESS;
    if success{ 
        status = CrossChainMsgStatus::SUCCESS;
    }else{
        status = CrossChainMsgStatus::FAILED;
    }
```

[handler_erc20.cairo#L108-L136](https://github.com/code-423n4/2024-08-chakra/blob/main/cairo/handler/src/handler_erc20.cairo#L108-L136)

```rust
fn receive_cross_chain_msg(ref self: ContractState, cross_chain_msg_id: u256, from_chain: felt252, to_chain: felt252,
from_handler: u256, to_handler: ContractAddress, payload: Array<u8>) -> bool{
    assert(to_handler == get_contract_address(),'error to_handler');

    assert(self.settlement_address.read() == get_caller_address(), 'not settlement');

    assert(self.support_handler.read((from_chain, from_handler)) && 
            self.support_handler.read((to_chain, contract_address_to_u256(to_handler))), 'not support handler');

    let message :Message= decode_message(payload);
    let payload_type = message.payload_type;
    assert(payload_type == PayloadType::ERC20, 'payload type not erc20');
    let payload_transfer = message.payload;
    let transfer = decode_transfer(payload_transfer);
    assert(transfer.method_id == ERC20Method::TRANSFER, 'ERC20Method must TRANSFER');
    let erc20 = IERC20MintDispatcher{contract_address: self.token_address.read()};
    let token = IERC20Dispatcher{contract_address: self.token_address.read()};
    if self.mode.read() == SettlementMode::MintBurn{
        erc20.mint_to(u256_to_contract_address(transfer.to), transfer.amount);
Upgraded Q -> 3 from #553 [1730390878180]
Audit: 2024-08-chakra-findings
Severity: HIGH

Judge has assessed an item in Issue #553 as 3 risk. The relevant finding follows:

 ## [QA-02] `CreatedCrossChainTx` contains wrong `token`

**Issue Description:**

`CreatedCrossChainTx` struct record, created in `ChakraSettlementHandler::cross_chain_erc20_settlement` uses `address(this)` instead of `token` of the Handler. If we take a look at the struct:

[ChakraSettlementHandler.sol](https://github.com/code-423n4/2024-08-chakra/blob/main/solidity/handler/contracts/ChakraSettlementHandler.sol#L145)

```solidity
struct CreatedCrossChainTx {
      uint256 txid;
      string from_chain;
      string to_chain;
      address from;
      uint256 to;
      address from_token;
      uint256 to_token;
      uint256 amount;
      CrossChainTxStatus status;
  }
```

we will see that the 6th param is named `from_token`, and then in `cross_chain_erc20_settlement`:

```solidity
create_cross_txs[txid] = CreatedCrossChainTx(
          txid,
          chain,
          to_chain,
          msg.sender,
          to,
          address(this),//6th param
          to_token,
          amount,
          CrossChainTxStatus.Pending
      );
```

While this struct is not used in either one of the functions later, the `receive_cross_chain_callback` uses the storage variable and doesn’t rely on the param from the struct.

**Recommendation:**

Use the `token` storage variable instead of `address(this)`:

```diff
create_cross_txs[txid] = CreatedCrossChainTx(
          txid,
          chain,
          to_chain,
          msg.sender,
          to,
-         address(this),
+         token, 
          to_token,
          amount,
          CrossChainTxStatus.Pending
      );
```
Upgraded Q -> 3 from #555 [1730390219813]
Audit: 2024-08-chakra-findings
Severity: HIGH

Judge has assessed an item in Issue #555 as 3 risk. The relevant finding follows:

 ## [L-04] incorrect event data in `ChakraSettlementHandler.CreatedCrossChainTx`
File:
https://github.com/code-423n4/2024-08-chakra/blob/d0d45ae1d26ca1b87034e67180fac07ce9642fd9/solidity/handler/contracts/ChakraSettlementHandler.sol#L160
https://github.com/code-423n4/2024-08-chakra/blob/d0d45ae1d26ca1b87034e67180fac07ce9642fd9/solidity/handler/contracts/ChakraSettlementHandler.sol#L218
According to `CreatedCrossChainTx`'s [defination](https://github.com/code-423n4/2024-08-chakra/blob/d0d45ae1d26ca1b87034e67180fac07ce9642fd9/solidity/handler/contracts/BaseSettlementHandler.sol#L53-L63), the value in [ChakraSettlementHandler.sol#L160](https://github.com/code-423n4/2024-08-chakra/blob/d0d45ae1d26ca1b87034e67180fac07ce9642fd9/solidity/handler/contracts/ChakraSettlementHandler.sol#L160) should be `from_token`, which should be **token**, instead of `address(this)`, which means `from_handle`
Same issue happends in [ChakraSettlementHandler.sol#L218](https://github.com/code-423n4/2024-08-chakra/blob/d0d45ae1d26ca1b87034e67180fac07ce9642fd9/solidity/handler/contracts/ChakraSettlementHandler.sol#L218)
Upgraded Q -> 3 from #569 [1730389316390]
Audit: 2024-08-chakra-findings
Severity: HIGH

Judge has assessed an item in Issue #569 as 3 risk. The relevant finding follows:

 ## [L-07] `receive_cross_chain_msg()` and `receive_cross_chain_callback()` miss access control on Ethereum

In the current implementation of `ChakraSettlement` smart contract, `receive_cross_chain_msg()` and `receive_cross_chain_callback()` miss access control meaning anybody can call the functions. This can lead to some unexpected scenarios where users can manipulate the values that are sent by the Chakra Network:

https://github.com/code-423n4/2024-08-chakra/blob/main/solidity/settlement/contracts/ChakraSettlement.sol#L256-264
```
function receive_cross_chain_callback(
        uint256 txid,
        string memory from_chain,
        uint256 from_handler,
        address to_handler,
        CrossChainMsgStatus status,
        uint8 sign_type,
        bytes calldata signatures
    ) external {

```

https://github.com/code-423n4/2024-08-chakra/blob/main/solidity/settlement/contracts/ChakraSettlement.sol#L170-180
```
 function receive_cross_chain_msg(
        uint256 txid,
        string memory from_chain,
        uint256 from_address,
        uint256 from_handler,
        address to_handler,
        PayloadType payload_type,
        bytes calldata payload,
        uint8 sign_type, // validators signature type /  multisig or bls sr25519
        bytes calldata signatures // signature array
    ) external 


```

### Recommendation

Implement `onlyNetwork` modifier or create some other functionality to prevent users from calling the sensitive functions.


## [L-08] `receive_cross_chain_msg()` and `receive_cross_chain_callback()` miss access control on Starknet


In the current implementation of `settlement` smart contract, `receive_cross_chain_msg()` and `receive_cross_chain_callback()` miss access control meaning anybody can call the functions. This can lead to some unexpected scenarios where users can manipulate the values that are sent by the Chakra Network:

https://github.com/code-423n4/2024-08-chakra/blob/main/cairo/handler/src/settlement.cairo#L393-403
```
  fn receive_cross_chain_callback(
            ref self: ContractState,
            cross_chain_msg_id: felt252,
            from_chain: felt252,
            to_chain: felt252,
            from_handler: u256,
            to_handler: ContractAddress,
            cross_chain_msg_status: u8,
            sign_type: u8,
            signatures: Array<(felt252, felt252, bool)>,
        ) -> bool 

```

https://github.com/code-423n4/2024-08-chakra/blob/main/cairo/handler/src/settlement.cairo#L325-336
```
   fn receive_cross_chain_msg(
            ref self: ContractState,
            cross_chain_msg_id: u256,
            from_chain: felt252,
            to_chain: felt252,
            from_handler: u256,
            to_handler: ContractAddress,
            sign_type: u8,
            signatures: Array<(felt252, felt252, bool)>,
            payload:
Upgraded Q -> 3 from #569 [1730389273653]
Audit: 2024-08-chakra-findings
Severity: HIGH

Judge has assessed an item in Issue #569 as 3 risk. The relevant finding follows:

 ## [L-01] `toChain` address is not verified in `receive_cross_chain_msg()` on Ethereum

`receive_cross_chain_msg()` has not any `toChain` verification the same way it's done on Starknet:

https://github.com/code-423n4/2024-08-chakra/blob/main/solidity/settlement/contracts/ChakraSettlement.sol#L170-180
```
function receive_cross_chain_msg(
        uint256 txid,
        string memory from_chain,
        uint256 from_address,
        uint256 from_handler,
        address to_handler,
        PayloadType payload_type,
        bytes calldata payload,
        uint8 sign_type, // validators signature type /  multisig or bls sr25519
        bytes calldata signatures // signature array
    ) 
```

https://github.com/code-423n4/2024-08-chakra/blob/main/cairo/handler/src/settlement.cairo#L337
```
  assert(to_chain == self.chain_name.read(), 'error to_chain');
```

`to_chain` should correspond to the chain of the settlement contract. Otherwise, some unexpected scenarios can occur when the settlement of the incorrect chain is called.

### Recommendation

Include `to_chain` check in the parameters of the `receive_cross_chain_msg()`.
Upgraded Q -> 3 from #572 [1730388681403]
Audit: 2024-08-chakra-findings
Severity: HIGH

Judge has assessed an item in Issue #572 as 3 risk. The relevant finding follows:

 ## Title (5/6)
Wrong data values written in Solidity event.

## Description
The next events write wrong information into events:

1. File: solidity/handler/contracts/ChakraSettlementHandler.sol
Function: cross_chain_erc20_settlement
[![GitHub code snippet](https://github.com/code-423n4/2024-08-chakra/blob/main/solidity/handler/contracts/ChakraSettlementHandler.sol#L212C1-L222C11)](https://github.com/code-423n4/2024-08-chakra/blob/main/solidity/handler/contracts/ChakraSettlementHandler.sol#L212C1-L222C11)
```solidity
emit CrossChainLocked(
    txid,
    msg.sender,
    to,
    chain,
    to_chain,
    address(this), <- This should be from token addr not this contract addr.
    to_token,
    amount,
    mode
);

// event fields detail:
event CrossChainLocked(
    uint256 indexed txid,
    address indexed from,
    uint256 indexed to,
    string from_chain,
    string to_chain,
    address from_token,
    uint256 to_token,
    uint256 amount,
    SettlementMode mode
);
```

2. File ChakraSettlement.sol
Function: solidity/settlement/contracts/ChakraSettlement.sol
[![GitHub code snippet](https://github.com/code-423n4/2024-08-chakra/blob/main/solidity/settlement/contracts/ChakraSettlement.sol#L235C1-L243C11)](https://github.com/code-423n4/2024-08-chakra/blob/main/solidity/settlement/contracts/ChakraSettlement.sol#L235C1-L243C11)
```solidity
emit CrossChainHandleResult(
    txid,
    status,
    contract_chain_name, <- This should be from_chain
    from_chain,          <- This should be to_chain
    address(to_handler), <- This should be from_handler
    from_handler,        <- This should be to_handler
    payload_type
);

event CrossChainHandleResult(
    uint256 indexed txid,
    CrossChainMsgStatus status,
    string from_chain,
    string to_chain,
    address from_handler,
    uint256 to_handler,
    PayloadType payload_type
);
```

## Impact
Offchain platforms reading wrong information from blockchain network.

## Proof of Concept
N/A

## Tools Used
Manual revision

## Recommended Mitigation Steps
Fix variables used that do not correspond with the event fields.



## Title (6/6)
Wrongly filling from_token in create_cross_txs struct mapping variable.

## Description
The from_token field is being assigned with handler contract address (this) instead of the from_token: AddressCast.to_uint256(token)

File: solidity/handler/contracts/ChakraSettlementHandler.sol
[![GitHub code snippet](https://github.com/code-423n4/2024-08-chakra/blob/main/solidity/handler/contracts/ChakraSettlementHandler.sol#L154C1-L164C15)](https://github.com/code-423n4/2024-08-chakra/blob/main/solidity/handler/contracts/ChakraSettlementHandler.sol#L154C1-L164C15)
```solidity
function cross_chain_erc20_settlement( ... ) external {
    // ...
    
    create_cross_txs[txid] = CreatedCrossChainTx(
        txid,
Signatures can be reused, allowing users to withdraw funds repeatedly
Audit: 2024-08-chakra-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-08-chakra/blob/abef77d95866f2fec93270491fc5abc9ab14f86d/cairo/handler/src/settlement.cairo#L339-L350


# Vulnerability details

## Impact
Signatures can be reused, allowing users to withdraw funds repeatedly.

## Proof of Concept
background:
1. When cross-chain, chain A sends an event to indicate a cross-chain request, and then executes the receive_cross_chain_msg function on chain B to withdraw the user's cross-chain funds.
2. The [correct signature is required when executing the receive_cross_chain_msg function](https://github.com/code-423n4/2024-08-chakra/blob/abef77d95866f2fec93270491fc5abc9ab14f86d/cairo/handler/src/settlement.cairo#L339-L350).
```cairo
            // verify signatures
            let mut message_hash: felt252 = LegacyHash::hash(from_chain, (cross_chain_msg_id, to_chain, from_handler, to_handler));
            let payload_span = payload.span();
            let mut i = 0;
            loop {
                if i > payload_span.len()-1{
                    break;
                }
                message_hash = LegacyHash::hash(message_hash, * payload_span.at(i));
                i += 1;
            };
            self.check_chakra_signatures(message_hash, signatures);

        fn check_chakra_signatures(
            self: @ContractState, message_hash: felt252, signatures: Array<(felt252, felt252, bool)>
        ){
            let mut pass_count = 0;
            let mut i = 0;
            loop {
                if i > signatures.len()-1{
                    break;
                }
                let (r,s,y) = * signatures.at(i);
                let pub_key: felt252 = recover_public_key(message_hash,r,s,y).unwrap();
                if self.chakra_validators_pubkey.read(pub_key) > 0{
                    pass_count += 1;
                }
                i += 1;
            };
            assert(pass_count >= self.required_validators_num.read(), 'Not enough validate signatures');
        }
    }
```
3. The nonce is not used in the signature, and the cross-chain status of this cross-chain transaction is not verified on chain B. So the signature can be reused.


In summary, after the user successfully cross-chain, he can continue to use the same signature to withdraw money from chain B until the corresponding handler is empty.

## Tools Used
manual

## Recommended Mitigation Steps
It is recommended to use a nonce for signatures, or verify whether each transaction has been withdrawn, and do not allow repeated withdrawals.


## Assessed type

Other
receive_cross_chain_msg function always returns true, regardless of the outcome of its operations
Audit: 2024-08-chakra-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-08-chakra/blob/d0d45ae1d26ca1b87034e67180fac07ce9642fd9/cairo/handler/src/handler_erc20.cairo#L108-L136


# Vulnerability details

## Impact
Silent failures in cross-chain operations.

## Proof of Concept
In the current implementation of receive_cross_chain_msg, the function performs several operations including validation checks, token minting, and token transfers. However, regardless of whether these operations succeed or encounter issues, the function unconditionally returns true at the end.

```
   fn receive_cross_chain_msg(ref self: ContractState, cross_chain_msg_id: u256, from_chain: felt252, to_chain: felt252,
        from_handler: u256, to_handler: ContractAddress, payload: Array<u8>) -> bool{
            assert(to_handler == get_contract_address(),'error to_handler');

            assert(self.settlement_address.read() == get_caller_address(), 'not settlement');

            assert(self.support_handler.read((from_chain, from_handler)) && 
                    self.support_handler.read((to_chain, contract_address_to_u256(to_handler))), 'not support handler');

            let message :Message= decode_message(payload);
            let payload_type = message.payload_type;
            assert(payload_type == PayloadType::ERC20, 'payload type not erc20');
            let payload_transfer = message.payload;
            let transfer = decode_transfer(payload_transfer);
            assert(transfer.method_id == ERC20Method::TRANSFER, 'ERC20Method must TRANSFER');
            let erc20 = IERC20MintDispatcher{contract_address: self.token_address.read()};
            let token = IERC20Dispatcher{contract_address: self.token_address.read()};
            if self.mode.read() == SettlementMode::MintBurn{
                erc20.mint_to(u256_to_contract_address(transfer.to), transfer.amount);
            }else if self.mode.read() == SettlementMode::LockMint{
                erc20.mint_to(u256_to_contract_address(transfer.to), transfer.amount);
            }else if self.mode.read() == SettlementMode::BurnUnlock{
                token.transfer(u256_to_contract_address(transfer.to), transfer.amount);
            }else if self.mode.read() == SettlementMode::LockUnlock{
                token.transfer(u256_to_contract_address(transfer.to), transfer.amount);
            }
            
            return true;
        }
```

https://github.com/code-423n4/2024-08-chakra/blob/d0d45ae1d26ca1b87034e67180fac07ce9642fd9/cairo/handler/src/handler_erc20.cairo#L108-L136

The function doesn't distinguish between successful and failed executions.

## Tools Used
Manual review

## Recommended Mitigation Steps
Modify the function to return meaningful status information. 


## Assessed type

Context
Incorrect settlement mode used on the destination chain
Audit: 2024-08-chakra-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-08-chakra/blob/abef77d95866f2fec93270491fc5abc9ab14f86d/solidity/handler/contracts/ChakraSettlementHandler.sol#L325-L350


# Vulnerability details

## Impact
In the Chakra cross-chain messaging system, a pair of `ChakraSettlement` and `ChakraSettlementHandler` contracts are deployed on each supported chain to manage cross-chain transactions. Four settlement modes are supported: `MintBurn`, `LockUnlock`, `LockMint`, and `BurnUnlock`. Each mode can be used on any chain. When a cross-chain message is initiated on the source chain, assets are managed according to the specified settlement mode:
```solidity
function cross_chain_erc20_settlement(
    string memory to_chain,
    uint256 to_handler,
    uint256 to_token,
    uint256 to,
    uint256 amount
) external {

    if (mode == SettlementMode.MintBurn) {
        _erc20_lock(msg.sender, address(this), amount);
    } else if (mode == SettlementMode.LockUnlock) {
        _erc20_lock(msg.sender, address(this), amount);
    } else if (mode == SettlementMode.LockMint) {
        _erc20_lock(msg.sender, address(this), amount);
    } else if (mode == SettlementMode.BurnUnlock) {
        _erc20_burn(msg.sender, amount);
    }

    // --SNIP
}
```
The issue is that the destination chain uses its own settlement mode, rather than the mode used to initiate the cross-chain message on the source chain:
```solidity
function receive_cross_chain_msg(
    uint256 /**txid */,
    string memory from_chain,
    uint256 /**from_address */,
    uint256 from_handler,
    PayloadType payload_type,
    bytes calldata payload,
    uint8 /**sign type */,
    bytes calldata /**signaturs */
) external onlySettlement returns (bool) {
    // --SNIP
>>>    if (mode == SettlementMode.MintBurn) { // audit-sus shouldn't we compare the mod of the source chain that initiated the cross-chain msg?
        _erc20_mint(
            AddressCast.to_address(transfer_payload.to),
            transfer_payload.amount
        );
            eturn true;
>>>    } else if (mode == SettlementMode.LockUnlock) {
        _erc20_unlock(
            AddressCast.to_address(transfer_payload.to),
            transfer_payload.amount
        );

        return true;
>>>    } else if (mode == SettlementMode.LockMint) {
        _erc20_mint(
            AddressCast.to_address(transfer_payload.to),
            transfer_payload.amount
        );
        return true;
>>>    } else if (mode == SettlementMode.BurnUnlock) {
        _erc20_unlock(
            AddressCast.to_address(transfer_payload.to),
            transfer_payload.amount
        );
        return true;
    }

    // --SNIP
        
}
```
This discrepancy can lead to inconsistencies in the ERC20 token state across chains. The settlement mode on the destination chain should match the mode used to initiate the cross-chain message.

For example, consider a scenario where the settlement mode on Ethereum is `MintBurn`, and on Polygon, it is `LockUnlock`. If a