xanoutas/solidity-security-findings huggingface dataset:
CreatedCrossChainTx struct has incorrectly assigned values when sending a cross-chain tx
Audit: 2024-08-chakra-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-08-chakra/blob/main/solidity/handler/contracts/ChakraSettlementHandler.sol#L160
https://github.com/code-423n4/2024-08-chakra/blob/main/solidity/handler/contracts/ChakraSettlementHandler.sol#L218


# Vulnerability details

## Impact

In the current implementation of `ChakraSettlementHandler`, the function `cross_chain_erc20_settlement()` serves as an entry point for users to send cross-chain transactions. The problem is that, when creating `CreatedCrossChainTx` for a txId and saving it in `create_cross_chain_txs`, the protocol makes a mistake by storing `address(this)` as `from_token` parameter when in reality it's an address of the `from_handler`

## Proof of Concept

Take a look at the current functionality of `cross_chain_erc20_settlement()`:

https://github.com/code-423n4/2024-08-chakra/blob/main/solidity/handler/contracts/ChakraSettlementHandler.sol#L268#L154-164
```
 create_cross_txs[txid] = CreatedCrossChainTx(
                txid,
                chain,
                to_chain,
                msg.sender,
                to,
                address(this),
                to_token,
                amount,
                CrossChainTxStatus.Pending
            );

```

The struct has `address(this)` parameter on the place where `token` of the handler contract should be:

https://github.com/code-423n4/2024-08-chakra/blob/main/solidity/handler/contracts/BaseSettlementHandler.sol#L59
```
  struct CreatedCrossChainTx {
        uint256 txid;
        string from_chain;
        string to_chain;
        address from;
        uint256 to;
        address from_token;
        uint256 to_token;
        uint256 amount;
        CrossChainTxStatus status;
    }

```

This would result in storing an incorrect information about cross-chain tx and violation of the spec. Moreover, it might potentially affect offchain services as the same mistake is repeated when emitting an event:

https://github.com/code-423n4/2024-08-chakra/blob/main/solidity/handler/contracts/ChakraSettlementHandler.sol#L268#L212-222
```
  emit CrossChainLocked(
            txid,
            msg.sender,
            to,
            chain,
            to_chain,
            address(this),
            to_token,
            amount,
            mode
        );
```


## Tools Used

Manual review.

## Recommended Mitigation Steps

Change `address(this)` parameter on `token` that corresponds to the token of the settlement handler contract.


## Assessed type

Other
Anybody can call TokenRoles_init()
Audit: 2024-08-chakra-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-08-chakra/blob/main/solidity/handler/contracts/TokenRoles.sol#L19


# Vulnerability details

## Impact

`TokenRoles` contract is the contract that helps to add / remove operators. However, the initialization function can be called by anybody and anybody can change the owner of the contract.

## Proof of Concept

Current functionality of the initialization:

https://github.com/code-423n4/2024-08-chakra/blob/main/solidity/handler/contracts/TokenRoles.sol#L19-23
```
    function __TokenRoles_init(address _owner, address _operator) public {
        __Ownable_init(_owner);
        _grantRole(DEFAULT_ADMIN_ROLE, _owner);
        _grantRole(OPERATOR_ROLE, _operator);
    }
```

As you can see, the function has `public` visibility meaning anybody can call the function and initialize it by, for example, front-running the owner. 

## Tools Used

Manual review.

## Recommended Mitigation Steps

The owner of the contract should be set in the constructor and only he can call the initialization functionality.


## Assessed type

Access Control
Rogue validators can bypass the minimul required validator signature for processing crossChain transaction
Audit: 2024-08-chakra-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-08-chakra/blob/abef77d95866f2fec93270491fc5abc9ab14f86d/solidity/settlement/contracts/ChakraSettlement.sol#L194-L197
https://github.com/code-423n4/2024-08-chakra/blob/abef77d95866f2fec93270491fc5abc9ab14f86d/solidity/settlement/contracts/SettlementSignatureVerifier.sol#L202-L210


# Vulnerability details

## Impact
Please note the issue exist on both solidity and cairo code, therefore the have the same fix.
When processing a crossChain transaction and callback inside [ChakraSettlement.sol](https://github.com/code-423n4/2024-08-chakra/blob/main/solidity/settlement/contracts/ChakraSettlement.sol) there is signature verification to ensure only validators signed the message and the minimum validator signature threshold is met.
```solidity
 require(
                signature_verifier.verify(message_hash, signatures, sign_type),
                "Invalid signature"
            );
``` 

The verify signature checks that the signature type is 0 and process to call the verifyECDSA() function.

```solidity
function verify(
        bytes32 msgHash,
        bytes calldata signatures,
        uint8 sign_type
    ) external view returns (bool) {
        if (sign_type == 0) {
            return verifyECDSA(msgHash, signatures);
        } else {
            return false;
        }
    }
```

However in verifyECDSA() function there is no check to ensure a single validator did not sign multiple times to pass the threshold.
```solidity
function verifyECDSA(
        bytes32 msgHash,
        bytes calldata signatures
    ) internal view returns (bool) {
        require(
            signatures.length % 65 == 0,
            "Signature length must be a multiple of 65"
        );

        uint256 len = signatures.length;
        uint256 m = 0;
        for (uint256 i = 0; i < len; i += 65) {
            bytes memory sig = signatures[i:i + 65];
            if (
                validators[msgHash.recover(sig)] && ++m >= required_validators // àaudit here
            ) {
                return true; 
            }
        }

        return false;
    }
```
And also on the cairo code we get the same error [here](https://github.com/code-423n4/2024-08-chakra/blob/d0d45ae1d26ca1b87034e67180fac07ce9642fd9/cairo/handler/src/settlement.cairo#L173-L190)
```cairo
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
Insufficient signature verification in Cairo contract
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#L184
https://github.com/code-423n4/2024-08-chakra/blob/abef77d95866f2fec93270491fc5abc9ab14f86d/cairo/handler/src/settlement.cairo#L350


# Vulnerability details

## Impact

`ChakraSettlement` contract in cairo code is vulnerable to a replay attack where a single malicious validator can reuse their signature multiple times to bypass the security checks. This vulnerability allows a malicious validator to manipulate the `receive_cross_chain_msg function`, potentially leading to unauthorized token minting, or token transfers. The exploit leverages the `check_chakra_signatures` function, which only counts the total number of valid signatures but does not verify that each signature corresponds to a unique validator. By repeatedly using the same valid signature, a single validator could meet the required number of validators (required_validators_num), thus compromising the integrity of the cross-chain message validation.

## Proof of Concept

The vulnerability is in the `check_chakra_signatures` function in the Cairo code of the ChakraSettlement contract.This function counts the number of valid signatures without checking if each signature comes from a unique validator. Consequently, a single malicious validator can reuse their signature multiple times to meet the required number of validator signatures (required_validators_num). This oversight allows a malicious validator to bypass the security check

```cairo
        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');
        }
```
Similarly, in the receive_cross_chain_msg function, there is no check for unique signatures or validators. A malicious validator could submit multiple instances of their valid signature to pass the verification check.This allows attacker to send malicious payload which would allow him  exploit the contract by minting tokens or transferring tokens to himself.

```
       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, bo
Upgraded Q -> 2 from #550 [1730401091932]
Audit: 2024-08-chakra-findings
Severity: MEDIUM

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

 ## [QA-05] Inability to Customize `ChakraToken` Decimals During Deployment on Starknet
### Impact
The ChakraToken is designed to have customizable decimals upon deployment, as confirmed by the sponsor and demonstrated in the Solidity implementation:
```solidity
contract ChakraToken is ERC20Upgradeable, TokenRoles, IERC20Mint, IERC20Burn {
    uint8 set_decimals;
    function initialize( address _owner, address _operator, string memory _name, string memory _symbol, uint8 _decimals) public initializer {
        __TokenRoles_init(_owner, _operator);
        __ERC20_init(_name, _symbol);
>>>        set_decimals = _decimals;
    }

    function decimals() public view override returns (uint8) {
        return set_decimals;
    }
}
```
However, on Starknet, the Chakra token is hardcoded to `18` decimals (the default value), with no option to specify a custom decimal value during deployment:
```rs
mod ckrBTC {
    // --SNIP
    #[constructor]
    fn constructor(ref self: ContractState, owner: ContractAddress) {
        self.ownable.initializer(owner);

        let name = "ckrBTC";
        let symbol = "CBTC";

        self.erc20.initializer(name, symbol);
        self.chakra_managers.write(owner, 1);
    }
}
```
This limitation may result in inconsistencies between the Solidity-based Chakra tokens and those deployed on Starknet, especially if a non-default decimal value is required.

### Recommended Mitigation Steps
Consider overriding the `decimals` method in the Cairo implementation of the Chakra token. You can add the following code to `ckr_btc.cairo`:
```rs
#[external(v0)]
impl ERC20MetadataImpl of interface::IERC20Metadata<ContractState> {
    fn decimals(self: @ContractState) -> u8 {
        // Change the `8` below to the desired number of decimals
        8
    }
}
```
Alternatively, you can follow the [storage approach](https://docs.openzeppelin.com/contracts-cairo/0.9.0/erc20#the_storage_approach) outlined in the OpenZeppelin documentation
Upgraded Q -> 2 from #544 [1730393948584]
Audit: 2024-08-chakra-findings
Severity: MEDIUM

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

 ## [L-1] Possible loss of funds due to the lack of handler validation in `cross_chain_erc20_settlement`

The lack of handler validation in `cross_chain_erc20_settlement` in 
Possible lock or burn of caller's funds, depending on the settlement mode. [ChakraSettlementHandler.sol#L111](https://github.com/code-423n4/2024-08-chakra/blob/f61c899c22492bdf5bdcb07cdb62ea9b4cd38825/solidity/handler/contracts/ChakraSettlementHandler.sol#L111)

**Recommended Mitigation Steps**
Add a check whether the handler is whitelisted to the `cross_chain_erc20_settlement` function.
Upgraded Q -> 2 from #547 [1730393806035]
Audit: 2024-08-chakra-findings
Severity: MEDIUM

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

 ### [L-01] Missing validation in the source chain if the destination chain handler is in the source chain whitelist. 

### Impact
The validation of the destination chain/target chain handler is needed in the source chain from where the message needs to be originated as mentioned in the main invariant point 
> • The handler receiving a cross-chain message must be on the whitelist for the source chain

But the EVM side of the code has this. Users can just specify any nonzero handler as both the code just validate null inputs. Though the impact is low it breaks the invariant mentioned above.

### Code Snippet
EVM `cross_chain_settelmenet.sol` function in `ChakraSettlementHandler.sol` contract
https://github.com/code-423n4/2024-08-chakra/blob/d0d45ae1d26ca1b87034e67180fac07ce9642fd9/solidity/handler/contracts/ChakraSettlementHandler.sol#L111-L223
```
 require(amount > 0, "Amount must be greater than 0");
        require(to != 0, "Invalid to address");
        require(to_handler != 0, "Invalid to handler address");
        require(to_token != 0, "Invalid to token address");

        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
```

### Recommendation
As the invariant documentation mentioned add the validation for the receiving end `handler` address as contract already maintains the whitelist of valid handler in the form of `from_chain` and `from_handler`
```
function cross_chain_erc20_settlement(
        string memory to_chain,
        uint256 to_handler,
        uint256 to_token,
        uint256 to,
        uint256 amount
    ) external {
// null validation snip
 require(is_valid_handler(to_chain, to_handler) == false),'not support handler')
// snip
}
```
Upgraded Q -> 2 from #558 [1730393659574]
Audit: 2024-08-chakra-findings
Severity: MEDIUM

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

 ## [L-08] Inappropriate address in CrossChainMsg event
### Proof of Concept
https://github.com/code-423n4/2024-08-chakra/blob/d0d45ae1d26ca1b87034e67180fac07ce9642fd9/cairo/handler/src/settlement.cairo#L299-L311
`from_address` use `get_tx_info().unbox().account_contract_address` which is the account contract from which this transaction originates. If the initiator of tx isn't the caller of handler contract, `from_address` in settlement contract is different from `from` in handler contract which use `get_caller_address()`. It leads to chaos about `from_address`.
### Recommended Mitigation Steps
Recommend to add `from_address` as input of `send_cross_chain_msg` function and use it to CrossChainMsg event.
Upgraded Q -> 2 from #558 [1730393537368]
Audit: 2024-08-chakra-findings
Severity: MEDIUM

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

 ## [L-03] wrong address stored in receive_cross_txs mapping
### Proof of Concept
https://github.com/code-423n4/2024-08-chakra/blob/d0d45ae1d26ca1b87034e67180fac07ce9642fd9/solidity/settlement/contracts/ChakraSettlement.sol#L205-L214
```
    struct ReceivedCrossChainTx {
        uint256 txid;
        string from_chain;
        string to_chain;
        uint256 from_address;
        uint256 from_handler;
        address to_handler;
        bytes payload;
        CrossChainMsgStatus status;
    }
```
According to the definition of struct ReceivedCrossChainTx, `address(this)` should be changed to `to_handler`.
### Recommended Mitigation Steps
```diff
        receive_cross_txs[txid] = ReceivedCrossChainTx(
            txid,
            from_chain,
            contract_chain_name,
            from_address,
            from_handler,
-           address(this),
+           to_handler,
            payload,
            CrossChainMsgStatus.Pending
        );
```
Upgraded Q -> 2 from #558 [1730393472093]
Audit: 2024-08-chakra-findings
Severity: MEDIUM

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

 ## [L-01] wrong address stored in created_tx mapping
### Proof of Concept
https://github.com/code-423n4/2024-08-chakra/blob/d0d45ae1d26ca1b87034e67180fac07ce9642fd9/cairo/handler/src/handler_erc20.cairo#L184-L194
`from` should be caller of `cross_chain_erc20_settlement` function. `get_contract_address()` is equal to `address(this)` in solidity. `get_caller_address()` is equal to `msg.sender` in solidity.
### Recommended Mitigation Steps
```diff
            let tx: CreatedCrossChainTx = CreatedCrossChainTx{
                    tx_id: tx_id,
                    from_chain: from_chain,
                    to_chain: to_chain,
-                   from: get_contract_address(),
+                   from: get_caller_address(),                    
                    to: to,
                    from_token: self.token_address.read(),
                    to_token: to_token,
                    amount: amount,
                    tx_status: CrossChainTxStatus::PENDING
                };
```
Upgraded Q -> 2 from #130 [1730393195293]
Audit: 2024-08-chakra-findings
Severity: MEDIUM

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

 ## [03] `ChakraSettlement.receive_cross_chain_msg` function incorrectly uses `address(this)` as data for `ReceivedCrossChainTx` struct's `to_handler` when setting `receive_cross_txs[txid]`

### Description
The `ChakraSettlement.receive_cross_chain_msg` function uses `address(this)` as the data for `to_handler` of the `ReceivedCrossChainTx` struct when setting `receive_cross_txs[txid]`, which is incorrect because `address(this)` is the address of the `ChakraSettlement` contract that is not the `to_handler` address. When there is a need to retrieve the `receive_cross_txs[txid]`'s `to_handler` for a `txid`, the `ChakraSettlement` contract's address is incorrectly considered as such `to_handler`; such misleading `to_handler` data can cause the protocol to malfunction.

https://github.com/code-423n4/2024-08-chakra/blob/f61c899c22492bdf5bdcb07cdb62ea9b4cd38825/solidity/settlement/contracts/ChakraSettlement.sol#L170-L244
```solidity
    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 {
        ...

        receive_cross_txs[txid] = ReceivedCrossChainTx(
            txid,
            from_chain,
            contract_chain_name,
            from_address,
            from_handler,
@>          address(this),
            payload,
            CrossChainMsgStatus.Pending
        );

        ...
    }
```

https://github.com/code-423n4/2024-08-chakra/blob/f61c899c22492bdf5bdcb07cdb62ea9b4cd38825/solidity/settlement/contracts/ChakraSettlement.sol#L31-L40
```solidity
    struct ReceivedCrossChainTx {
        uint256 txid;
        string from_chain;
        string to_chain;
        uint256 from_address;
        uint256 from_handler;
@>      address to_handler;
        bytes payload;
        CrossChainMsgStatus status;
    }
```

### Recommended Mitigation
The `ChakraSettlement.receive_cross_chain_msg` function can be updated to use its `to_handler` input value as the data for `to_handler` of the `ReceivedCrossChainTx` struct when setting `receive_cross_txs[txid]`.
Upgraded Q -> 2 from #114 [1730392971111]
Audit: 2024-08-chakra-findings
Severity: MEDIUM

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

 ## [L-11] provided wrong data to `CreatedCrossChainTx.from` when `cross_chain_erc20_settlement` on `handler_erc20.cairo`.

`get_contract_address()` provided as `from` instead of `get_caller_address()`.

https://github.com/code-423n4/2024-08-chakra/blob/main/cairo/handler/src/handler_erc20.cairo#L188

```cairo
            // pub struct CreatedCrossChainTx {
            //     tx_id : felt252,
            //     from_chain: felt252,
            //     to_chain: felt252,
            //     from: ContractAddress,
            //     to: u256,
            //     from_token: ContractAddress,
            //     to_token: u256,
            //     amount: u256,
            //     tx_status: u8
            //  }
            // @audit - (DONE) - compare with L1 struct doesnt matter
            let tx: CreatedCrossChainTx = CreatedCrossChainTx{
                    tx_id: tx_id,
                    from_chain: from_chain,
                    to_chain: to_chain,
>>>                 from: get_contract_address(),
                    to: to,
                    from_token: self.token_address.read(),
                    to_token: to_token, 
                    amount: amount,
                    tx_status: CrossChainTxStatus::PENDING
                };
```

### Mitigation

provide `get_caller_address()` to `CreatedCrossChainTxfrom`.