Write assertions and test them with the Credible Layer
OwnableAssertion.a.sol
. Here’s the complete code first, followed by a detailed breakdown:
getCallInputs
, can be variable, due to unknown lengths of the call inputs.
We are actively working to improve this as soon as possible. Staying mindful of gas consumption is in general a good practice.
See the Assertion Patterns for more details on ways to optimize gas consumption.
Assertion
, which provides the base functionality and cheatcodes for assertionsOwnable
)pcl
.ph.getAssertionAdopter()
cheatcode to get the address of the contract we want to protect.triggers
function is required by the Assertion
interface.registerCallTrigger
specifies the function selector of the assertion function to run and the function selector of the protected contract function that should trigger the assertion.ph.forkPreTx()
: Creates a snapshot of the blockchain state before the transaction.ph.forkPostTx()
: Creates a snapshot of the blockchain state after the transaction.ph
namespace gives access to the Credible Layer cheatcodes, which provide utility functions for assertions. For more information see the cheatcodes documentation.forkPreTx()
and forkPostTx()
to compare values before and after transactions.forkPreCall()
and forkPostCall()
to compare values before and after specific calls.console.log()
in assertion functions to print debug information to the console during testing with pcl test
.OwnableAssertion
: Imports the assertion we created that we want to testOwnable
: Imports the protocol contract that our assertion is protectingCredibleTest
: Provides special testing utilities for assertion testing, including the cl
cheatcode interfaceTest
: Standard testing base contract from Forge, providing utilities like vm.prank
and vm.expectRevert
CredibleTest
and Test
which provides testing utilitiesCredibleTest
provides the cl
cheatcode interface for testing assertionsTest
is the standard Forge test base contractassertionAdopter
is the contract we’re protectingnewOwner
is used to test ownership transfersinitialOwner
is the owner of the contract before the tests are runOwnable
contract for testingvm.deal
cl.assertion()
: Sets up the assertion to be run on the next transaction
adopter
: Address of contract to protectcreateData
: Bytecode of the assertion contractfnSelector
: Selector of the assertion function to runvm.prank()
: Simulates a call from the owner’s addressvm.expectRevert()
: Explicitly expects the assertion to revert with “Ownership has changed”assertionAdopter.transferOwnership(newOwner)
: Simulates a transaction that changes ownershipassertEq(assertionAdopter.owner(), initialOwner)
: Checks that the owner didn’t changecl
is the cheatcode exposed by the CredibleTest
contract used specifically for testing assertions. It provides tools to validate your assertions under different conditions without having to deploy them to a real blockchain.transferOwnership
will not revert if the assertion passes so we don’t need to use vm.expectRevert()
cl.assertion()
to register assertions that will be run on the next transactionvm.prank
, vm.deal
) to set up test scenariosvm.expectRevert()
to verify that the assertion reverts when expected