feat(contracts): Foundry workspace + CharonLiquidator skeleton#36
Merged
feat(contracts): Foundry workspace + CharonLiquidator skeleton#36
Conversation
…#11) Lays the on-chain foundation. The contract shape and the storage layout are fixed by this commit so the Rust tx builder (#14) and the fork tests (#22) can target stable signatures; the actual liquidation + flash-loan + swap logic is the next commit (#12). - `contracts/` Foundry workspace, `forge-std` pinned via submodule - `foundry.toml` — solc 0.8.24, optimizer 1M runs, 100-char fmt, BSC RPC + etherscan endpoints driven from `${BNB_HTTP_URL}` / `${BSCSCAN_API_KEY}` so fork tests run against mainnet state - `src/CharonLiquidator.sol`: - `executeLiquidation(LiquidationParams)` entrypoint, `onlyOwner` - `executeOperation(...)` Aave V3 callback, gated by `msg.sender == AAVE_POOL` AND `initiator == address(this)` - both stub bodies revert with explicit "not yet implemented" so any accidental skeleton deploy fails loud before touching funds - `rescue(token, to, amount)` fully implemented as a safety hatch (handles native BNB and ERC-20, checks transfer return value) - `LiquidationExecuted` + `Rescued` events - immutables: owner, AAVE_POOL, SWAP_ROUTER (zero-address guarded) - `src/interfaces/`: minimal IFlashLoanSimpleReceiver, IERC20, IAaveV3Pool, IVToken stubs — no external libs, all defined inline - Skipped: Balancer `receiveFlashLoan` callback (not on BSC), IComet/IMorpho (out of v0.1 scope) `forge build` clean, `forge fmt --check` clean.
This was referenced Apr 22, 2026
Closed
drop the floating `^0.8.24` caret across CharonLiquidator.sol and the four inline interfaces. pins deployed-bytecode producing solc to a single known version and removes risk of a future 0.8.x patch release subtly changing codegen, optimizer behaviour or metadata hash. closes #113
BNB Chain has not adopted the Shanghai hard fork and rejects the PUSH0 opcode. solc >= 0.8.20 emits PUSH0 by default, so contracts compiled with the prior config would revert on first touch when deployed to BSC. pinning the target to paris keeps our bytecode compatible with the live chain until BSC enables Shanghai. closes #114
the forge-std submodule is already pinned by gitlink to commit 2999b6563e1f07971a09d48b82f3fac910d72a05 (v1.15.0 + 15) in the parent repo's index, but .gitmodules carried no explanation. add comments recording the pin, noting the absence of `branch =` is deliberate (so `git submodule update` tracks the recorded commit, not a moving tip), and warning against `--remote` in CI. closes #115
remove the open `receive() external payable { }` hatch on
CharonLiquidator so misrouted or griefing bnb transfers now revert
instead of silently accumulating. v0.1 does not handle the vBNB
native market; when it is added, a sender-gated receive() will be
introduced. existing rescue(address(0), ...) still recovers bnb
credited via selfdestruct.
switch the native-bnb branch of rescue() from `payable(to).transfer`
to `payable(to).call{value: amount}("")` with a checked success
return. the 2300-gas stipend of `transfer`/`send` is insufficient
post-EIP-1884 for gnosis safe and other smart-wallet recipients,
which would otherwise trap funds. erc-20 path is unchanged.
closes #117
step-11 requires a passing forge test suite. add one that covers the shape of the deployed skeleton without any fork dependency: - constructor zero-address guards and owner/immutable binding - onlyOwner on executeLiquidation and rescue - per-field input validation inside executeLiquidation (seven require branches reached before the skeleton's final revert) - executeOperation `!pool` and `!initiator` security gates - rescue() erc-20 and native-bnb happy paths, zero-recipient and zero-amount reverts, plus the post-#117 `call`-based bnb path against a gas-hungry contract recipient that would reject a 2300-gas `transfer` stipend - post-#117 no-receive policy: direct bnb sends must revert uses only forge-std and two in-file mocks (MockERC20, GasHungryReceiver); pinned at solidity 0.8.24. fork-based end-to-end coverage remains tracked under issue #22. closes #116
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #12
Lays the on-chain foundation. Contract shape and storage layout are fixed by this commit so the Rust tx builder and fork tests can target stable signatures; actual liquidation + flash-loan + swap logic is the next PR.
contracts/Foundry workspace,forge-stdpinned via submodulefoundry.toml— solc 0.8.24, optimizer 1M runs, 100-char fmt, BSC RPC + etherscan endpoints driven from${BNB_HTTP_URL}/${BSCSCAN_API_KEY}src/CharonLiquidator.sol:executeLiquidation(LiquidationParams)entrypoint,onlyOwnerexecuteOperation(...)Aave V3 callback, gated bymsg.sender == AAVE_POOLANDinitiator == address(this)rescue(token, to, amount)fully implemented as a safety hatch (handles native BNB + ERC-20, checks transfer return value)LiquidationExecuted+Rescuedeventssrc/interfaces/: minimal IFlashLoanSimpleReceiver, IERC20, IAaveV3Pool, IVToken — no external libsreceiveFlashLoan(not on BSC), IComet/IMorpho (out of v0.1 scope)forge buildclean,forge fmt --checkclean.Depends on #11 (
feat/10-chainlink-pricecache).