xanoutas/solidity-security-findings huggingface dataset:
Actors need to maintain two Kakarot accounts for L1 to L2 messaging
Audit: 2024-09-kakarot-findings
Severity: HIGH

# Lines of code

https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/solidity_contracts/src/L1L2Messaging/L1KakarotMessaging.sol#L32-L45
https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/kakarot.cairo#L369-L385
https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/library.cairo#L421-L438


# Vulnerability details

## Proof of Concept
<details>
<summary>
	<a href="https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/solidity_contracts/src/L1L2Messaging/L1KakarotMessaging.sol#L32-L45">L1KakarotMessaging</ahref>
</summary>
  
```solidity
    function sendMessageToL2(address to, uint248 value, bytes calldata data) external payable {
        uint256 totalLength = data.length + 4;
        uint256[] memory convertedData = new uint256[](totalLength);
        convertedData[0] = uint256(uint160(AddressAliasHelper.applyL1ToL2Alias(msg.sender))); <@udit
        convertedData[1] = uint256(uint160(to));
        convertedData[2] = uint256(value);
        convertedData[3] = data.length;
        for (uint256 i = 4; i < totalLength; ++i) {
            convertedData[i] = uint256(uint8(data[i - 4]));
        }

        // Send the converted data to L2
        starknetMessaging.sendMessageToL2{value: msg.value}(kakarotAddress, HANDLE_L1_MESSAGE_SELECTOR, convertedData);
    }
```
</details> 

<details>
<summary>
<a href="https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/kakarot.cairo#L369-L385">Kakarot</ahref>
</summary>
  
```cairo
@l1_handler
func handle_l1_message{
    syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr, bitwise_ptr: BitwiseBuiltin*
}(from_address: felt, l1_sender: felt, to_address: felt, value: felt, data_len: felt, data: felt*) {
    alloc_locals;
    Pausable.assert_not_paused();
    let l1_messaging_contract_address = Kakarot.get_l1_messaging_contract_address();
    if (from_address != l1_messaging_contract_address) {
        return ();
    }

    let (_, state, _, _) = Kakarot.handle_l1_message(l1_sender, to_address, value, data_len, data); <@udit

    // Reverted or not - commit the state change. If reverted, the state was cleared to only contain gas-related changes.
    Starknet.commit(state);
    return ();
}
```

</details>
  
<details>
<summary>
<a href="https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/library.cairo#L421-L438">Library</ahref>
</summary>
  
```cairo
    func handle_l1_message{
        syscall_ptr: felt*,
        pedersen_ptr: HashBuiltin*,
        range_check_ptr,
        bitwise_ptr: BitwiseBuiltin*,
    }(l1_sender: felt, to_address: felt, value: felt, data_len: felt, data: felt*) -> (
        model.EVM*, model.State*, felt, felt
    ) {
        // TODO: ensure fair gas limits and prices
        let (val_high, val_low) = split_felt(value);
        tempvar value_u256 = new Ui
Opcodes consuming a lot of steps at the cost of few gas can be exploited
Audit: 2024-09-kakarot-findings
Severity: HIGH

# Lines of code

https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/interpreter.cairo#L50


# Vulnerability details

## Impact

Opcodes like `PUSH`, `MSTORE`, etc costs very few gas but consumes a lot of steps. So if a contract repeatedly executes these opcodes, it can consume more than `10,000,000` whereas the max steps allowed is `10,000,000` as per [starknet docs](https://docs.starknet.io/tools/limits-and-triggers/) ( refer: Max transaction size (Cairo steps) ). So in mainnet, this transaction will revert due to `out of steps` error. So any contract using these opcodes will be vulnerable to this issue or if a contract makes a callback to another contract by making sure to only send limited gas and handle the revert case properly, the other contract can use these opcodes repeatedly to make the transaction revert forcefully ( even at the cost of around 3000 gas ).

## Proof of Concept

Consider the following code:
```huff
#define macro MAIN() = takes(0) returns(0) {
    0x00 // retSize
    0x00 // retOffset
    0x00 // argsSize
    0x00 // argsOffset
    0x000000000000000000000000000000ca1100f023 // address
    0xbb8 // gas = 3000
    staticcall
    stop
}
```

Save the above code in a file name `opcodes_parent.huff` ( You can refer [Installing Huff](https://docs.huff.sh/get-started/installing/), if you don't have huff installed ).

The code will make a `STATICCALL` by only passing 3000 gas.

The above code can be converted to bytecode using the following command:

```bash
huffc opcodes_parent.huff --bytecode
```

The output will be:

```
600f8060093d393df35f5f5f5f64ca1100f023610bb8fa00
```

The runtime code is ( after removing the first few bytes which are responsible for deployment ):

```
5f5f5f5f64ca1100f023610bb8fa00
```

Also, consider the following code:
```huff
#define macro MAIN() = takes(0) returns(0) {
    loop:
        0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
        0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
        0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
        0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
        0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

    0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
    loop
    jumpi
}
```

Save the above code in a file name `opcodes.huff`.

The code will execute `PUSH32` opcode multiple times.

The above code can be converted to bytecode using the following command:

```bash
huffc opcodes.huff --bytecode
```

The output will be:

```
60cb8060093d393df35b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffff
Loading whole bytecode in memory can lead to running out of steps even using limited gas
Audit: 2024-09-kakarot-findings
Severity: HIGH

# Lines of code

https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/accounts/library.cairo#L486


# Vulnerability details

## Impact

To load the bytecode of any contract, [library.cairo::load_bytecode](https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/accounts/library.cairo#L486) is called ( [library.cairo::eth_call](https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/library.cairo#L103) -> [starknet.cairo::get_bytecode](https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/backend/starknet.cairo#L101) -> [account_contract.cairo::bytecode](https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/accounts/account_contract.cairo#L212) -> [library.cairo::bytecode](https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/accounts/library.cairo#L269) -> [library.cairo::load_bytecode](https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/accounts/library.cairo#L486) ). The problem is that whenever any contract is called, the complete bytecode is loaded into memory even though not all of it will be executed, thus it can run out of steps while loading the whole bytecode. 

NOTE: Maximum length of the bytecode is 24KB as per [ethereum docs](https://ethereum.org/en/developers/docs/smart-contracts/#limitations).

So any contract calling multiple different contracts with large bytecode will be vulnerable to this issue or if a contract makes a callback to another contract by making sure to only send limited gas and handle the revert case properly, the other contract can call multiple different contracts with large bytecode to make the transaction revert forcefully.

## Proof of Concept

Consider a case where a contract make `STATICCALL` to another contract ( malicious ) by passing only 50k gas ( so that the transaction on evm level doesn't revert due to out of gas error ):

```huff
#define macro MAIN() = takes(0) returns(0) {   
    0x0
    0x0
    0x0
    0x0
    0x000000000000000000000000000000ca1100f023 // child
    0xc350 // 50000
    staticcall
    0x01
    0x00
    mstore
    0x20
    0x00
    return
}
```

Save the above code in a file name parent.huff ( You can refer [Installing Huff](https://docs.huff.sh/get-started/installing/), if you don't have huff installed ).

The above code simply makes a `STATICCALL` to the contract `0x000000000000000000000000000000ca1100f023` and then return 0x01.

The above code can be converted to bytecode using the following command:

```bash
huffc parent.huff --bytecode
```

The output will be:

```
60168060093d393df35f5f5f5f64ca1100f02361c350fa60015f5260205ff3
```

The runtime code is ( after removing the first few bytes which are responsible for deployment ):

```
5f5f5f5f64ca1100f02361c350fa60015f5260205ff3
```

Consider the malicious contr
Three valid signatures for the same message
Audit: 2024-09-kakarot-findings
Severity: HIGH

# Lines of code

https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/precompiles/ec_recover.cairo#L40


# Vulnerability details

## Impact
On Ethereum, it's possible to create **two** different valid signatures for the same message (known as ECDSA Signature Malleability). However, on Kakarot, you can create **three** different valid signatures for the same message. This happens because, on Ethereum, if the value of `s` is higher than the maximum valid range, it returns `address(0)`. On Kakarot, in this case, it returns a valid address.

## Proof of Concept

If `r` and `v` are in the valid range, and `s` is between `1` and `secp256k1n`, the `ecrecover` function behaves the same on both Ethereum and Kakarot.

- On Ethereum, if the value of `s` is higher than `secp256k1n`, it returns `address(0)`.
- On Kakarot, if the value of `s` is higher than `secp256k1n`, it returns an address equivalent to `s + secp256k1n`.

Here's an example for better clarity. The `ecrecover` function for the following inputs will return the same result `0x992FEaf0E360bffaeAcf57c28D2a3F5059Fe0982`:

- On Ethereum:
   - input1: `r = 1, v = 27, s = 2`
   - input2: `r = 1, v = 28, s = secp256k1n - 2 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413F`

- On Kakarot:
   - input1: `r = 1, v = 27, s = 2`
   - input2: `r = 1, v = 28, s = secp256k1n - 2 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413F`
   - input3: `r = 1, v = 27, s = secp256k1n + 2 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364143`

While inputs 1 and 2 behave as expected, input 3 highlights the problem. With input 3, Ethereum's `ecrecover` returns `address(0)`, but Kakarot returns the same result as input1 and input2.

This shows that a malleability attack on Kakarot can be done in two ways, whereas on Ethereum, it can only be done in one.

In simple terms, on Ethereum, a malleability attack can be done by changing the `v` from `27` to `28` (or vice versa) and swapping `s` with `secp256k1n - s`:
- `r, s, v`
- `r, secp256k1n - s, v = {27 -> 28, 28 -> 27}`

On Kakarot, the malleability attack can be done in two ways: either by changing `s` to `secp256k1n + s` (as long as it's not larger than `2**256 - 1`) or using the same method as Ethereum by changing the `v` and swapping `s` with `secp256k1n - s`:
- `r, s, v`
- `r, secp256k1n - s, v = {27 -> 28, 28 -> 27}`
OR:
- `r, s, v`
- `r, secp256k1n + s, v`

The value of `s` needs to be limited in the `ec_recover::run` function to make sure it's within the valid range.

```rust
    func run{
        syscall_ptr: felt*,
        pedersen_ptr: HashBuiltin*,
        range_check_ptr,
        bitwise_ptr: BitwiseBuiltin*,
    }(_address: felt, input_len: felt, input: felt*) -> (
        output_len: felt, output: felt*, gas_used: felt, reverted: felt
    ) {
        alloc_locals;

        let (input_padded) = alloc();
        slice(input_padded, input_len, input, 0, 4 * 32);
Missing enforcment of valid `r` range in `ecrecover`
Audit: 2024-09-kakarot-findings
Severity: HIGH

# Lines of code

https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/precompiles/ec_recover.cairo#L40


# Vulnerability details

## Impact
The valid range of `r` is not being enforced when calling ecrecover. This causes an issue where if `r` is set outside its valid range (as defined by the Ethereum yellow paper), Kakarot will panic, while on Ethereum, it will simply return `address(0)`.

## Proof of Concept

According to the Ethereum yellow paper, an ECDSA signature is only valid if all the following conditions are true:
 - `0 < r < secp256k1n`
 - `0 < s < secp256k1n / 2 + 1` 
- `v = 27 || 28`
where `secp256k1n = 115792089237316195423570985008687907852837564279074904382605163141518161494337 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141`
https://ethereum.github.io/yellowpaper/paper.pdf


If `s` and `v` are valid, but `r` exceeds its maximum value (i.e., `r >= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141`):

 - On Ethereum, ecrecover returns `address(0)`.
 - On Kakarot, it causes a panic with errors like "Invalid argument" and "Option::unwrap failed."

This is a significant difference between Kakarot and Ethereum.

The issue occurs when the precompiler `ecrecover` is invoked, and the following function is executed:
```rust
    func run{
        syscall_ptr: felt*,
        pedersen_ptr: HashBuiltin*,
        range_check_ptr,
        bitwise_ptr: BitwiseBuiltin*,
    }(_address: felt, input_len: felt, input: felt*) -> (
        output_len: felt, output: felt*, gas_used: felt, reverted: felt
    ) {
        alloc_locals;

        let (input_padded) = alloc();
        slice(input_padded, input_len, input, 0, 4 * 32);

        let v_uint256 = Helpers.bytes32_to_uint256(input_padded + 32);
        let v = Helpers.uint256_to_felt(v_uint256);

        if ((v - 27) * (v - 28) != 0) {
            let (output) = alloc();
            return (0, output, GAS_COST_EC_RECOVER, 0);
        }

        let msg_hash = Helpers.bytes_to_uint256(32, input_padded);
        let r = Helpers.bytes_to_uint256(32, input_padded + 32 * 2);
        let s = Helpers.bytes_to_uint256(32, input_padded + 32 * 3);

        // v - 27, see recover_public_key comment
        let (helpers_class) = Kakarot_cairo1_helpers_class_hash.read();
        let (success, recovered_address) = ICairo1Helpers.library_call_recover_eth_address(
            class_hash=helpers_class, msg_hash=msg_hash, r=r, s=s, y_parity=v - 27
        );

        if (success == 0) {
            let (output) = alloc();
            return (0, output, GAS_COST_EC_RECOVER, 0);
        }

        let (output) = alloc();
        memset(output, 0, 12);
        Helpers.split_word(recovered_address, 20, output + 12);

        return (32, output, GAS_COST_EC_RECOVER, 0);
    }
```
https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/precompiles/ec_recover.cairo#L40

This function does not enforce the val
Incorrect calculation in `Gas::max_memory_expansion_cost` for high offset zero size argument
Audit: 2024-09-kakarot-findings
Severity: HIGH

# Lines of code

https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/gas.cairo#L140


# Vulnerability details

## Impact

The [gas.cairo::max_memory_expansion_cost](https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/gas.cairo#L140) function is used to compute the maximum expansion cost given two memory chunks based on the maximum offset reached by each chunk. The function is as follows:
```cairo
    // @notice Given two memory chunks, compute the maximum expansion cost
    //  based on the maximum offset reached by each chunk.
    // @dev Memory expansion cost is computed over the `low` parts of
    // the offsets and sizes. In the second step, we check whether the `high`
    // parts are non-zero and if so, we add the cost of expanding the memory by
    // 2**128 words (saturating).
    // @param words_len The current length of 256-bit words in memory.
    // @param offset_1 The offset of the first memory chunk as Uint256.
    // @param size_1 The size of the first memory chunk as Uint256.
    // @param offset_2 The offset of the second memory chunk as Uint256.
    // @param size_2 The size of the second memory chunk as Uint256.
    // @return cost The expansion gas cost for the chunk whose ending offset is the largest and the new size of the memory
    func max_memory_expansion_cost{range_check_ptr}(
        words_len: felt, offset_1: Uint256*, size_1: Uint256*, offset_2: Uint256*, size_2: Uint256*
    ) -> model.MemoryExpansion {
        alloc_locals;

        let (is_zero_1) = uint256_eq([size_1], Uint256(0, 0));
        let (is_zero_2) = uint256_eq([size_2], Uint256(0, 0));
        tempvar both_zero = is_zero_1 * is_zero_2;
        jmp no_expansion if both_zero != 0;

->      tempvar is_not_saturated = Helpers.is_zero(offset_1.high) * Helpers.is_zero(size_1.high) *
            Helpers.is_zero(offset_2.high) * Helpers.is_zero(size_2.high);
        tempvar is_saturated = 1 - is_not_saturated;
        tempvar range_check_ptr = range_check_ptr;
        jmp expansion_cost_saturated if is_saturated != 0;

        let max_offset_1 = (1 - is_zero_1) * (offset_1.low + size_1.low);
        let max_offset_2 = (1 - is_zero_2) * (offset_2.low + size_2.low);
        let max_expansion_is_2 = is_le_felt(max_offset_1, max_offset_2);
        let max_offset = max_offset_1 * (1 - max_expansion_is_2) + max_offset_2 *
            max_expansion_is_2;
        let (q, _) = unsigned_div_rem(max_offset, 2 ** 32);
        tempvar range_check_ptr = range_check_ptr;
        jmp expansion_cost_saturated if q != 0;

        let expansion = calculate_gas_extend_memory(words_len, max_offset);
        let expansion = model.MemoryExpansion(
            cost=expansion.cost, new_words_len=expansion.new_words_len
        );
        return expansion;

        no_expansion:
        let range_check_ptr = [fp - 8];
        let expansion = model.MemoryExpansion(cost=0, new_words_len=words_len);
Wrong gas price calculation in `eth_send_raw_unsigned_tx` could lead to suboptimal transaction pricing
Audit: 2024-09-kakarot-findings
Severity: MEDIUM

# Lines of code

https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/eth_rpc.cairo#L304-L307


# Vulnerability details

## Proof of Concept

`eth_rpc.cairo::eth_send_raw_unsigned_tx` underprices transactions, which could lead to delayed or failed transactions in congested network conditions.

Take a look at this part of the code:

https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/eth_rpc.cairo#L304-L307

```cairo
let possible_priority_fee = tx.max_fee_per_gas - block_base_fee;
let priority_fee_is_max_priority_fee = is_nn(
    possible_priority_fee - tx.max_priority_fee_per_gas
);
let priority_fee_per_gas = priority_fee_is_max_priority_fee * tx.max_priority_fee_per_gas + (
    1 - priority_fee_is_max_priority_fee
) * possible_priority_fee;
let effective_gas_price = priority_fee_per_gas + block_base_fee;
```

The problem is in the calculation of `priority_fee_per_gas`. The logic attempts to choose between `tx.max_priority_fee_per_gas` and `possible_priority_fee`, but it does so incorrectly.

The issue is that `priority_fee_is_max_priority_fee` is set to 1 when `possible_priority_fee` is greater than or equal to `tx.max_priority_fee_per_gas`, which is the opposite of what we actually want. This means that when the `possible_priority_fee` is larger, the function will choose `tx.max_priority_fee_per_gas` instead of the smaller value.

As a result, in some cases, `the priority_fee_per_gas` could be set higher/lower than intended leading to users paying more/less in gas fees than necessary.


In most cases, transactions may be underpriced relative to what the user is willing to pay. In congested network conditions, transactions may end up being delayed or failing to be processed cos they're not utilizing the full gas price the user was willing to pay.

#### Short Note:
> I discussed this issue with the sponsors and they confirmed this bug case

## Recommended Mitigation Steps

The calculation of `priority_fee_is_max_priority_fee` should be inverted. 

```diff
- let priority_fee_is_max_priority_fee = is_nn(
-     possible_priority_fee - tx.max_priority_fee_per_gas
- );
+ let priority_fee_is_max_priority_fee = is_nn(
+     tx.max_priority_fee_per_gas - possible_priority_fee
+ );
```






## Assessed type

Error
Upgraded Q -> 2 from #128 [1731055600750]
Audit: 2024-09-kakarot-findings
Severity: MEDIUM

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

 3. Missing chainid data length check
The cairo code while decoding several transaction types, checks the length of chainid as can be seen in the following functions: https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/utils/eth_transaction.cairo#L101-L157 https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/utils/eth_transaction.cairo#L164-L222 however when decoding a legacy transaction the chainid length check is missing which creates inconsistency in the codebase which can later lead to issues https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/utils/eth_transaction.cairo#L63-L78

// pre eip-155 txs have 6 fields, post eip-155 txs have 9 fields
if (items_len == 6) {
    tempvar is_some = 0;
    tempvar chain_id = 0;
} else {
    assert items_len = 9;
    assert items[6].is_list = FALSE;
    assert items[7].is_list = FALSE;
    assert items[8].is_list = FALSE;
    let chain_id = Helpers.bytes_to_felt(items[6].data_len, items[6].data);

    tempvar is_some = 1;
    tempvar chain_id = chain_id;
}
let is_some = [ap - 2];
let chain_id = [ap - 1];
handle_l1_message() uses invalid hard-coded parameters for execution
Audit: 2024-09-kakarot-findings
Severity: MEDIUM

# Lines of code

https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/library.cairo#L436


# Vulnerability details

## Proof of Concept

At the moment `handle_l1_message()` uses incorrect hard-coded values to send the call:

https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/library.cairo#L435-437
```
 return eth_call(
            0, l1_sender, to, 2100000000, 1, value_u256, data_len, data, 0, access_list
        );
```

It has `nonce` parameter that's equal to 0, `gasLimit` == 2100000000 and `gasPrice` == 1:

https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/library.cairo#L435-437
```
   func eth_call{
        syscall_ptr: felt*,
        pedersen_ptr: HashBuiltin*,
        range_check_ptr,
        bitwise_ptr: BitwiseBuiltin*,
    }(
        nonce: felt,
        origin: felt,
        to: model.Option,
        gas_limit: felt,
        gas_price: felt,
        value: Uint256*,
        data_len: felt,
        data: felt*,
        access_list_len: felt,
        access_list: felt*,
```

Nonce is always increased upon the transaction execution and cannot be equal always to 1 (for an account), gas limit that's set to 21e8 is highly unrealistic and will exceed the block limit of the transaction that's approximately 5e6 for the Starknet and about 30e6 for Ethereum. Gas price is also set to 1 but it has to be calculated using `priority_fee_per_gas + block_base_fee` as for other transactions.

## Recommended Mitigation Steps

Use different values (ideally, not hardcoded and calculated based on the inputs) for the `eth_call()` parameters.


## Assessed type

Other