A minimal, working template for writing, testing, and deploying Credible Layer assertions. This repo mirrors the public quickstart and keeps the steps as short as possible for first-time users.
assertions/src: Assertion contracts (Solidity)assertions/test: Assertion tests runnable withpcl testassertions/credible-example.toml: Example deployment configuration forpcl applysrc: Example protocols with intentional vulnerabilitiesscript: Deployment scripts for the example protocolslib: Submodules forcredible-std,forge-std, and OpenZeppelin
pclinstalled (quick path): https://docs.phylax.systems/credible/credible-install- Foundry (
forge,cast): https://getfoundry.sh/ - Git
- An RPC endpoint and funded wallet for a Credible Layer-enabled network
Quick install (macOS):
brew tap phylaxsystems/pcl
brew install phylaxFoundry install:
curl -L https://foundry.paradigm.xyz | bash
foundryupThis flow is the shortest path to a deployed assertion.
git clone --recurse-submodules https://github.com/phylaxsystems/credible-layer-starter.git
cd credible-layer-starterIf you already cloned:
git submodule update --init --recursivepcl testexport RPC_URL=... # chain RPC URL
forge script script/DeployOwnable.s.sol \
--rpc-url "$RPC_URL" \
--account <account_name> \
--broadcastpcl auth login- Open the login link in your browser.
- Create a project in the platform and link the Ownable contract address.
- Ownership is verified via the network's admin verifier (typically
owner()or allowlist-based).
Copy the example configuration and update it with your deployed contract address:
cp assertions/credible-example.toml assertions/credible.tomlEdit assertions/credible.toml:
environment = "production"
[contracts.ownable]
address = "<ADDRESS_OF_DEPLOYED_CONTRACT>"
name = "Ownable"
[[contracts.ownable.assertions]]
file = "assertions/src/OwnableAssertion.a.sol"pcl applyBy default, pcl apply looks for assertions/credible.toml. To use a different path:
pcl apply -c path/to/credible.tomlThis reads credible.toml, builds the assertion, and creates a release on the platform.
You'll be prompted to select a project (if project_id is not set in credible.toml) and to confirm the release.
- Open the release link returned by
pcl apply, or navigate to your project in app.phylax.systems. - Review and deploy the assertion to Staging or Production.
- After the timelock, it becomes staged/enforced and starts protecting transactions.
export OWNABLE_ADDRESS=0x... # deployed Ownable address
# Check current owner
cast call "$OWNABLE_ADDRESS" "owner()" --rpc-url "$RPC_URL"
# Attempt to transfer ownership (should be dropped if assertion is enforced)
cast send "$OWNABLE_ADDRESS" \
"transferOwnership(address)" 0x1234567890123456789012345678901234567890 \
--account <account_name> \
--rpc-url "$RPC_URL" \
--timeout 20
# Owner should be unchanged
cast call "$OWNABLE_ADDRESS" "owner()" --rpc-url "$RPC_URL"If the transaction times out, the assertion likely dropped it. Some clients require a higher gas price to replace dropped txs.
The repo includes two larger examples with dedicated assertions:
- Contract:
src/PhyLock.sol - Assertions:
PhyLockAssertion,OwnershipAssertion - Deploy:
script/DeployPhyLock.s.sol
- Contract:
src/SimpleLending.sol - Assertions:
SimpleLendingAssertion,PriceFeedAssertion - Deploy:
script/DeploySimpleLending.s.sol
The end-to-end flow is the same as the Ownable example:
- Deploy the contract(s)
- Create a project and link contract addresses
- Add the contracts and assertions to
credible.toml(seeassertions/credible-example.toml) pcl apply- Deploy in the platform (staging/production)
- Run the provided
casttransactions below
Use the commands below after you have deployed the contracts and deployed assertions in the platform.
Deploy these assertions in the platform before running the transactions:
PhyLockAssertionfor the PhyLock contractOwnershipAssertionfor the same contract
export PHYLOCK_ADDRESS=0x...
export RPC_URL=...
# Deposit 0.7 ETH
cast send "$PHYLOCK_ADDRESS" "deposit()" --value 0.7ether --account <account_name> --rpc-url "$RPC_URL"
# Withdraw 0.2 ETH
cast send "$PHYLOCK_ADDRESS" "withdraw(uint256)" 0.2ether --account <account_name> --rpc-url "$RPC_URL"
# Withdraw 69 ETH (should be dropped)
cast send "$PHYLOCK_ADDRESS" "withdraw(uint256)" 69ether --account <account_name> --rpc-url "$RPC_URL" --timeout 20
# Transfer ownership (should be dropped)
cast send "$PHYLOCK_ADDRESS" \
"transferOwnership(address)" 0x1234567890123456789012345678901234567890 \
--account <account_name> \
--rpc-url "$RPC_URL" \
--timeout 20 \
--gas-price 100000000000Make sure your credible.toml includes both the lending contract and the price feed contract, then deploy:
SimpleLendingAssertionforSimpleLendingPriceFeedAssertionfor the price feed
export LENDING_PROTOCOL=0x...
export TOKEN_ADDRESS=0x...
export PRICE_FEED=0x...
export RPC_URL=...
# Mint tokens to the lending protocol
cast send "$TOKEN_ADDRESS" "mint(address,uint256)" "$LENDING_PROTOCOL" 100000ether --account <account_name> --rpc-url "$RPC_URL"
# Deposit 0.5 ETH
cast send "$LENDING_PROTOCOL" "deposit()" --value 0.5ether --account <account_name> --rpc-url "$RPC_URL"
# Borrow 750 tokens
cast send "$LENDING_PROTOCOL" "borrow(uint256)" 750ether --account <account_name> --rpc-url "$RPC_URL"
# Withdraw collateral (should be dropped)
cast send "$LENDING_PROTOCOL" "withdraw(uint256)" 0.25ether --account <account_name> --rpc-url "$RPC_URL" --timeout 20
# Decrease price by 15% (should be dropped)
cast send "$PRICE_FEED" "setPrice(uint256)" 0.75ether --account <account_name> --rpc-url "$RPC_URL" --timeout 20 --gas-price 100000000000- Quickstart: https://docs.phylax.systems/credible/pcl-quickstart
- Apply assertions: https://docs.phylax.systems/credible/apply-assertions
- Deploy with the platform: https://docs.phylax.systems/credible/deploy-assertions-dapp
- Assertions Book: https://docs.phylax.systems/assertions-book/assertions-book-intro
- Examples: https://github.com/phylaxsystems/assertions-examples