A module for the Sky Protocol that enables permissionless execution of Star Spells in a separate transaction after they were "whitelisted" by the core spell.
The StarGuard module resolves multiple problems with direct inclusion of the Star spells into the Core spell, the main of which is the bottleneck caused by the size of the core spell "cast" transaction (limited by the max block size). This module fixes this problem by allowing permissionless execution of a Star spell after it has been "whitelisted" by the core spell.
In other words, it replaces current flow:
1st transaction: Anyone ──► Core Spell ─┬─► SubProxy A ──► Star Spell A1
└─► SubProxy B ──► Star Spell B1
with the updated flow:
1st transaction: Anyone ──► Core Spell ─┬─► StarGuard A.plot(Star Spell A1)
└─► StarGuard B.plot(Star Spell B1)
2nd transaction: Anyone ──────────────────► StarGuard A.exec() ──► SubProxy A ──► Star Spell A1
3rd transaction: Anyone ──────────────────► StarGuard B.exec() ──► SubProxy B ──► Star Spell B1
- The governance (any address in
wards) is considered to be fully trusted.StarGuard.wardsis expected to only containMCD_PAUSE_PROXY - The
SubProxyis expected to work correctly.SubProxy.wardsis expected to containStarGuard - The Star spells are fully trusted, expected to be validated accordingly
- Additional sanity checks are implemented as a precaution:
codehashenforcement at the time of the executionexec()reentrancy protectionSubProxy.wardscheck after payload execution to still containStarGuard(note: it's not technically possible to guarantee that another address was added there which can modifywardsin the following transaction)
- Expected to implement the required functions (i.e.,
execute()andisExecutable())
- Additional sanity checks are implemented as a precaution:
- Any other address: Untrusted
- Codehash validation of the payload at the time of the execution
- Configurable maximum delay – a deadline, after which the Star payload is no longer executable
- Validation that Star spell did not remove StarGuard from the authorized contracts
Each payload contract is required to provide certain external interfaces:
interface StarSpellLike {
/**
* @notice Executes actions performed on behalf of the `SubProxy` – i.e. the actual payload
* @dev Required, will be called by the StarGuard during permissionless execution
*/
function execute() external;
/**
* @notice Checks if the star payload is executable in the current block
* @dev Required, useful for implementing "earliest launch date" or "office hours" strategy
* @return result The result of the check (true = executable, false = not)
*/
function isExecutable() external view returns (bool result);
}MAINNET_RPC_URL(required for testing) – the RPC url to the Ethereum Mainnet nodeETHERSCAN_API_KEY(required for deployment) – the API key from Etherscan
- Provide required env variable outlined above
- Execute
make test
- To format solidity code, execute
make format - To verify solidity natspec, use
make lint-spec
To deploy the contract, you can use Deploy.s.sol script and only provide the subProxy address as a parameter to this script. Here are the example commands:
# To estimate gas for the script
forge script script/Deploy.s.sol:Deploy --fork-url mainnet --sig 'run(address)' 0x...
# To broadcast live and verify contract on etherscan
forge script script/Deploy.s.sol:Deploy --fork-url mainnet --sig 'run(address)' 0x... --broadcast --verify --account $KEYSTORE_NAME