Everything you need to get started with Ironblocks' Firewall using Foundry.
Using Hardhat?
we're working on a hardhat version of this repo - stay tuned
Table Of Contents
This project serves as a Hello World example for getting started with Ironblocks' Firewall.
It includes 2 (very) simple contracts to demonstrate how the Firewall works:
-
HelloFirewall.sol
- a simple counter-like smart contract -
HelloFirewallPolicy.sol
- a security policy that limits counter increments to a set threshold
- This project uses Foundry, so make sure you have it installed before continuing.
-
Build the project by running:
forge build
-
Open a new terminal, and start a local development node with Anvil by running:
anvil
-
Open a second terminal, and run the
SetupEverything
Solidity Script:forge script \ --broadcast \ --rpc-url "http://127.0.0.1:8545" \ --private-key "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" \ script/SetupEverything.s.sol
-
You'll find a convenience helper script under
bin/anvil/setup-everything.sh
that runs the above command. -
The private key belongs to the first account built into Anvil (i.e. the first test account).
Now that everything is deployed, if you try to call increment()
on the HelloFirewall
smart contract multiple times, you'll notice that only the first call works.
-
Run the
Increment
Solidity Script to increment the number stored by ourHelloFirewall
example contract:forge script \ --broadcast \ --rpc-url "http://127.0.0.1:8545" \ --private-key "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" \ script/hello-firewall/Increment.s.sol
-
Run the script again.
This time it, the call gets blocked by the Firewall.
The second transaction failed, because the HelloFirewallPolicy
is preventing increments larger than a configured threshold. For simplicity, the default threshold is set to 1
, so only the first increment call passes (i.e. we can't increment to a number larger than 1
).
-
Run the
setIncrementThreshold
Solidity Script, which is hardcoded to update the threshold to3
:forge script \ --broadcast \ --rpc-url "http://127.0.0.1:8545" \ --private-key "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" \ script/hello-firewall-policy/SetIncrementThreshold.s.sol
-
Now that the policy's configuration was updated, we can send 2 additional
Increment
requests by calling theIncrement
Solidity Script two more times:forge script \ --broadcast \ --rpc-url "http://127.0.0.1:8545" \ --private-key "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" \ script/hello-firewall/Increment.s.sol
* run this twice
-
Last, if you try to call
Increment
for a third time, it will again be prevented by theHelloFirewallPolicy
.
If you examine the SetupEverything
Solidity Script, you'll notice there are several steps required to protect a smart contract. Let's recap what contracts and configurations were set up.
For the purpose of simplicity, all the contracts that are deployed and used in this project are owned by the same account - the default first account provided by Anvil.
-
HelloFirewall.sol
- this is our demo counter smart contract -
HelloFirewallPolicy.sol
- this is our custom security policy, which prevents anyone from incrementing the counter above a configurable threshold -
Firewall.sol
- this is the smart contract for the Firewall. It provides methods that allow a Firewall Consumer to subscribe or unsubscribe to security policies. It also allows the Firewall Owner to approve or disapprove what security policies will be available to Firewall ConsumersThe
Firewall Owner
is the principal (person, people, or organization) that deployed the FirewallA
Firewall Consumer
is a smart contract - such as ourHelloFirewall.sol
- which inherits theFirewallConsumer.sol
contract so that it can consume security services from the Firewall.
-
Every transaction sent to our
HelloFirewall
contract will be examined theFirewall
. For this to work, we first need to tell it whatFirewall
to use.
We do this by callingsetFirewall(FIREWALL_ADDRESS)
on theHelloFirewall
smart contract. -
As an additional layer of security, only policies that have been approved by a
Firewall Owner
will be available toFirewall Consumers
for them to subscribe to.
This is done by callingsetPolicyStatus(POLICY_ADDRESS, BOOLEAN)
on theFirewall
.The
Firewall Owner
in this demo is the same account that deploys theHelloFirewall
.In real world scenarios, the
Firewall Owner
may be any principal (person, people, or organization), as governed or decentralized as needed (i.e. DAO etc.) -
Last, our
HelloFirewall
smart contract needs to tell theFirewall
what security policies should be configured to protect it. In our case, we tell theFirewall
that we want theHelloFirewallPolicy
security policy to protect all calls to our smart contract. We do this by callingaddGlobalPolicy(OUR_ADDRESS, POLICY_ADDRESS)
on theFirewall
.Note that within our
HelloFirewall
example contract, only functions that have thefirewallProtected
modifier will be protected by theFirewall
More advanced modifiers and configuration options are also available, see the official documentation for more info (link below)
- Official Documentation
- Discord Channel
- Website