From 70283a23ddfec42224c764e5af647af6e725984a Mon Sep 17 00:00:00 2001 From: danwt <30197399+danwt@users.noreply.github.com> Date: Tue, 18 Nov 2025 16:59:31 +0100 Subject: [PATCH] claude: fix(solidity): apply CEI pattern to memo contracts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix reentrancy vulnerabilities in HypERC20CollateralMemo and HypERC20Memo by following Checks-Effects-Interactions pattern. Read and clear _memo state BEFORE external calls to prevent reentrancy attacks when tokens have callbacks (ERC777, custom hooks). Changes: - HypERC20CollateralMemo: move memo read/delete before safeTransferFrom - HypERC20Memo: move memo read/delete before _burn - Add security comments explaining the CEI pattern Resolves dymensionxyz/hyperlane-deployments#85 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../contracts/token/extensions/HypERC20CollateralMemo.sol | 6 +++++- solidity/contracts/token/extensions/HypERC20Memo.sol | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/solidity/contracts/token/extensions/HypERC20CollateralMemo.sol b/solidity/contracts/token/extensions/HypERC20CollateralMemo.sol index 3c2c50b8b53..9d4113cb180 100644 --- a/solidity/contracts/token/extensions/HypERC20CollateralMemo.sol +++ b/solidity/contracts/token/extensions/HypERC20CollateralMemo.sol @@ -28,9 +28,13 @@ contract HypERC20CollateralMemo is HypERC20Collateral { function _transferFromSender( uint256 _amount ) internal virtual override returns (bytes memory) { - super._transferFromSender(_amount); + // Follow CEI pattern: read and clear _memo BEFORE external call + // to prevent reentrancy if wrappedToken has callbacks (ERC777, custom hooks) bytes memory memo = _memo; delete _memo; + + super._transferFromSender(_amount); + emit IncludedMemo(memo); return memo; } diff --git a/solidity/contracts/token/extensions/HypERC20Memo.sol b/solidity/contracts/token/extensions/HypERC20Memo.sol index 2c27e76e7d1..42f4db9f3ab 100644 --- a/solidity/contracts/token/extensions/HypERC20Memo.sol +++ b/solidity/contracts/token/extensions/HypERC20Memo.sol @@ -28,9 +28,13 @@ contract HypERC20Memo is HypERC20 { function _transferFromSender( uint256 _amount ) internal virtual override returns (bytes memory) { - super._transferFromSender(_amount); + // Follow CEI pattern: read and clear _memo BEFORE burn + // to prevent reentrancy if child contracts override token hooks with external calls bytes memory memo = _memo; delete _memo; + + super._transferFromSender(_amount); + emit IncludedMemo(memo); return memo; }