Use Case

Check that the implementation of a contract does not change. This works similarly when checking if the owner of a contract has changed.

This assertions is useful if you want to make sure that a contract is not unexpectedly upgraded or changed to an undesired implementation. For example it would be possible to define a list of allowed implementations that would be whitelisted and any other implementation would be considered an invalid state.

Explanation

The assertion checks if the address of a contract has changed after a transaction has been executed.

Code Example

// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

import {Assertion} from "../../lib/credible-std/Assertion.sol";

interface IImplementation {
    function implementation() external view returns (address);
}

contract ImplementationChange is Assertion {
    IImplementation public implementation = IImplementation(address(0xbeef));

    function fnSelectors() external pure override returns (bytes4[] memory assertions) {
        assertions = new bytes4[](1);
        assertions[0] = this.implementationChange.selector;
    }

    // Asssert that the implementation contract address doesn't change
    // during the state transition
    function implementationChange() external {
        ph.forkPreState();
        address preImpl = implementation.implementation();
        ph.forkPostState();
        address postImpl = implementation.implementation();
        require(preImpl == postImpl, "Implementation changed");
    }
}