diff --git a/src/lib/ClaimProcessorLogic.sol b/src/lib/ClaimProcessorLogic.sol index 5b17360..8d4ea39 100644 --- a/src/lib/ClaimProcessorLogic.sol +++ b/src/lib/ClaimProcessorLogic.sol @@ -53,6 +53,7 @@ import { SplitComponent, BatchClaimComponent, SplitBatchClaimComponent } from ". import { ClaimHashLib } from "./ClaimHashLib.sol"; import { ClaimProcessorLib } from "./ClaimProcessorLib.sol"; import { EfficiencyLib } from "./EfficiencyLib.sol"; +import { EventLib } from "./EventLib.sol"; import { FunctionCastLib } from "./FunctionCastLib.sol"; import { HashLib } from "./HashLib.sol"; import { IdLib } from "./IdLib.sol"; @@ -75,6 +76,7 @@ contract ClaimProcessorLogic is SharedLogic { using EfficiencyLib for bool; using EfficiencyLib for bytes32; using EfficiencyLib for uint256; + using EventLib for address; using FunctionCastLib for function(bytes32, uint256, uint256, bytes32, bytes32, function(address, address, uint256, uint256) internal returns (bool)) internal returns (bool); using FunctionCastLib for function(bytes32, uint256, uint256, bytes32, bytes32, bytes32, function(address, address, uint256, uint256) internal returns (bool)) internal returns (bool); using FunctionCastLib for function(bytes32, bytes32, uint256, uint256, bytes32, bytes32, function(address, address, uint256, uint256) internal returns (bool)) internal returns (bool); @@ -580,7 +582,7 @@ contract ClaimProcessorLogic is SharedLogic { qualificationMessageHash.signedBy(allocator, allocatorSignature, domainSeparator); // Emit claim event. - _emitClaim(sponsor, messageHash, allocator); + sponsor.emitClaim(messageHash, allocator); } /** diff --git a/src/lib/EventLib.sol b/src/lib/EventLib.sol new file mode 100644 index 0000000..4f7728e --- /dev/null +++ b/src/lib/EventLib.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.27; + +/** + * @title EventLib + * @notice Library contract implementing logic for internal functions to + * emit various events. + * @dev Note that most events are still emitted using inline logic; this + * library only implements a few events. + */ +library EventLib { + // keccak256(bytes("Claim(address,address,address,bytes32)")). + uint256 private constant _CLAIM_EVENT_SIGNATURE = 0x770c32a2314b700d6239ee35ba23a9690f2fceb93a55d8c753e953059b3b18d4; + + // keccak256(bytes("ForcedWithdrawalStatusUpdated(address,uint256,bool,uint256)")). + uint256 private constant _FORCED_WITHDRAWAL_STATUS_UPDATED_SIGNATURE = 0xe27f5e0382cf5347965fc81d5c81cd141897fe9ce402d22c496b7c2ddc84e5fd; + + /** + * @notice Internal function for emitting claim events. The sponsor and allocator + * addresses are sanitized before emission. + * @param sponsor The account sponsoring the compact that the claim is for. + * @param messageHash The EIP-712 hash of the claim message. + * @param allocator The account mediating the claim. + */ + function emitClaim(address sponsor, bytes32 messageHash, address allocator) internal { + assembly ("memory-safe") { + // Emit the Claim event: + // - topic1: Claim event signature + // - topic2: sponsor address (sanitized) + // - topic3: allocator address (sanitized) + // - topic4: caller address + // - data: messageHash + mstore(0, messageHash) + log4(0, 0x20, _CLAIM_EVENT_SIGNATURE, shr(0x60, shl(0x60, sponsor)), shr(0x60, shl(0x60, allocator)), caller()) + } + } + + /** + * @notice Internal function for emitting forced withdrawal status update events. + * @param id The ERC6909 token identifier of the resource lock. + * @param withdrawableAt The timestamp when withdrawal becomes possible. + */ + function emitForcedWithdrawalStatusUpdatedEvent(uint256 id, uint256 withdrawableAt) internal { + assembly ("memory-safe") { + // Emit ForcedWithdrawalStatusUpdated event: + // - topic1: Event signature + // - topic2: Caller address + // - topic3: Token id + // - data: [activating flag, withdrawableAt timestamp] + mstore(0, iszero(iszero(withdrawableAt))) + mstore(0x20, withdrawableAt) + log3(0, 0x40, _FORCED_WITHDRAWAL_STATUS_UPDATED_SIGNATURE, caller(), id) + } + } +} diff --git a/src/lib/SharedLogic.sol b/src/lib/SharedLogic.sol index b486802..87a32b6 100644 --- a/src/lib/SharedLogic.sol +++ b/src/lib/SharedLogic.sol @@ -15,35 +15,12 @@ contract SharedLogic is ConstructorLogic { using IdLib for uint256; using SafeTransferLib for address; - // keccak256(bytes("Claim(address,address,address,bytes32)")). - uint256 private constant _CLAIM_EVENT_SIGNATURE = 0x770c32a2314b700d6239ee35ba23a9690f2fceb93a55d8c753e953059b3b18d4; - // Storage slot seed for ERC6909 state, used in computing balance slots. uint256 private constant _ERC6909_MASTER_SLOT_SEED = 0xedcaa89a82293940; // keccak256(bytes("Transfer(address,address,address,uint256,uint256)")). uint256 private constant _TRANSFER_EVENT_SIGNATURE = 0x1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac728859; - /** - * @notice Internal function for emitting claim events. The sponsor and allocator - * addresses are sanitized before emission. - * @param sponsor The account sponsoring the compact that the claim is for. - * @param messageHash The EIP-712 hash of the claim message. - * @param allocator The account mediating the claim. - */ - function _emitClaim(address sponsor, bytes32 messageHash, address allocator) internal { - assembly ("memory-safe") { - // Emit the Claim event: - // - topic1: Claim event signature - // - topic2: sponsor address (sanitized) - // - topic3: allocator address (sanitized) - // - topic4: caller address - // - data: messageHash - mstore(0, messageHash) - log4(0, 0x20, _CLAIM_EVENT_SIGNATURE, shr(0x60, shl(0x60, sponsor)), shr(0x60, shl(0x60, allocator)), caller()) - } - } - /** * @notice Internal function for transferring ERC6909 tokens between accounts. Updates * both balances, checking for overflow and insufficient balance. This function bypasses diff --git a/src/lib/TransferLogic.sol b/src/lib/TransferLogic.sol index 9936e71..e5b13e0 100644 --- a/src/lib/TransferLogic.sol +++ b/src/lib/TransferLogic.sol @@ -7,6 +7,7 @@ import { SplitComponent, TransferComponent, SplitByIdComponent } from "../types/ import { ClaimHashLib } from "./ClaimHashLib.sol"; import { EfficiencyLib } from "./EfficiencyLib.sol"; +import { EventLib } from "./EventLib.sol"; import { FunctionCastLib } from "./FunctionCastLib.sol"; import { IdLib } from "./IdLib.sol"; import { SharedLogic } from "./SharedLogic.sol"; @@ -27,6 +28,7 @@ contract TransferLogic is SharedLogic { using ClaimHashLib for SplitBatchTransfer; using IdLib for uint256; using EfficiencyLib for bool; + using EventLib for address; using ValidityLib for uint96; using ValidityLib for uint256; using ValidityLib for bytes32; @@ -228,7 +230,7 @@ contract TransferLogic is SharedLogic { messageHash.signedBy(allocator, transferPayload.allocatorSignature, _domainSeparator()); // Emit Claim event. - _emitClaim(msg.sender, messageHash, allocator); + msg.sender.emitClaim(messageHash, allocator); } /** diff --git a/src/lib/WithdrawalLogic.sol b/src/lib/WithdrawalLogic.sol index 461cf93..59b8512 100644 --- a/src/lib/WithdrawalLogic.sol +++ b/src/lib/WithdrawalLogic.sol @@ -6,6 +6,7 @@ import { ResetPeriod } from "../types/ResetPeriod.sol"; import { SharedLogic } from "./SharedLogic.sol"; import { EfficiencyLib } from "./EfficiencyLib.sol"; +import { EventLib } from "./EventLib.sol"; import { IdLib } from "./IdLib.sol"; /** @@ -18,9 +19,7 @@ contract WithdrawalLogic is SharedLogic { using IdLib for uint256; using IdLib for ResetPeriod; using EfficiencyLib for uint256; - - // keccak256(bytes("ForcedWithdrawalStatusUpdated(address,uint256,bool,uint256)")). - uint256 private constant _FORCED_WITHDRAWAL_STATUS_UPDATED_SIGNATURE = 0xe27f5e0382cf5347965fc81d5c81cd141897fe9ce402d22c496b7c2ddc84e5fd; + using EventLib for uint256; // Storage scope for forced withdrawal activation times: // slot: keccak256(_FORCED_WITHDRAWAL_ACTIVATIONS_SCOPE ++ account ++ id) => activates. @@ -48,7 +47,7 @@ contract WithdrawalLogic is SharedLogic { } // emit the ForcedWithdrawalStatusUpdated event. - _emitForcedWithdrawalStatusUpdatedEvent(id, withdrawableAt); + id.emitForcedWithdrawalStatusUpdatedEvent(withdrawableAt); } /** @@ -77,7 +76,7 @@ contract WithdrawalLogic is SharedLogic { } // emit the ForcedWithdrawalStatusUpdated event. - _emitForcedWithdrawalStatusUpdatedEvent(id, uint256(0).asStubborn()); + id.emitForcedWithdrawalStatusUpdatedEvent(uint256(0).asStubborn()); return true; } @@ -134,24 +133,6 @@ contract WithdrawalLogic is SharedLogic { } } - /** - * @notice Private function for emitting forced withdrawal status update events. - * @param id The ERC6909 token identifier of the resource lock. - * @param withdrawableAt The timestamp when withdrawal becomes possible. - */ - function _emitForcedWithdrawalStatusUpdatedEvent(uint256 id, uint256 withdrawableAt) private { - assembly ("memory-safe") { - // Emit ForcedWithdrawalStatusUpdated event: - // - topic1: Event signature - // - topic2: Caller address - // - topic3: Token id - // - data: [activating flag, withdrawableAt timestamp] - mstore(0, iszero(iszero(withdrawableAt))) - mstore(0x20, withdrawableAt) - log3(0, 0x40, _FORCED_WITHDRAWAL_STATUS_UPDATED_SIGNATURE, caller(), id) - } - } - /** * @notice Private pure function for computing the storage slot for a forced * withdrawal activation timestamp.