> For the complete documentation index, see [llms.txt](https://zokyo-auditing-tutorials.gitbook.io/zokyo-tutorials/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://zokyo-auditing-tutorials.gitbook.io/zokyo-tutorials/tutorials/tutorial-4-block.chainid-domain_separator-and-eip-2612-permit/examples.md).

# Examples

{% hint style="info" %}
[**Book an audit with Zokyo**](https://www.zokyo.io/)
{% endhint %}

{% hint style="info" %}
**Understanding the Examples:** In the "Examples" section, we delve into practical instances of front-running vulnerabilities unearthed from actual bug bounty reports, Code Arena analyses, and more. By studying these real-life cases, you'll gain a deeper, more tangible understanding of unsafe casting and its potential impact, enhancing your auditing skills in a practical and impactful way.
{% endhint %}

**Example 1:**[ **Immutable DOMAIN\_SEPARATOR With Stored ChainId**](https://github.com/code-423n4/2021-11-malt-findings/issues/349)

Real-life Bug Find With Payout

Consider a system where the domain separator in a contract following EIP-712 is calculated at the contract initialization and then stored in an immutable variable. This variable is used in further operations like message signing. The issue arises if a hard fork happens after the contract deployment. In the event of a fork, the `block.chainid` changes, but the stored domain separator remains the same on both chains, making it invalid on the forked chain.

```
// Pseudocode
constructor() {
    domainSeparator = keccak256(
        abi.encode(
            EIP712DOMAIN_TYPEHASH,
            name,
            version,
            block.chainid,
            address(this)
        )
    );
}
```

In the constructor, `domainSeparator` is calculated using `block.chainid` at the time of deployment and stored in an immutable variable.

Recommended Mitigation Steps:

Dynamically calculate the domain separator to take into account the possible changes of `block.chainid`. This can be done by adding a function that returns the domain separator, calculated with the current `block.chainid`.

{% hint style="info" %}
function getDomainSeparator() public view returns (bytes32) {&#x20;

return keccak256( abi.encode( EIP712DOMAIN\_TYPEHASH, name, version, block.chainid, address(this) ) );&#x20;

}
{% endhint %}

**Example 2: Static Domain Separator in EIP-2612 Implementation**

Real-life Bug Find With Payout

***EIP-2612 permit***&#x20;

Consider an ERC-20 token that implements the EIP-2612 permit mechanism. The contract calculates the chainid during its execution in the constructor and permanently stores it in an immutable variable. If Ethereum forks in the future, the `block.chainid` will change but the stored chainid used for permits will not, thus breaking the token functionality on the forked chain.

```
constructor() {
    chainid = block.chainid;
}
```

The issue here is that `chainid` is being calculated and stored during contract initialization, and it is not updated in the event of a chain split.

Recommended Mitigation Steps:

The chainid should be calculated dynamically on each permit invocation. As a gas optimization, the pre-calculated hash for the permits can be stored to an immutable variable, and a validation can occur on the permit function that ensures the current chainid is equal to the one of the cached hash. If not, it should be recalculated on the spot.

```
// Pseudocode
function getChainId() public view returns (uint256) {
    return block.chainid;
}
```
