diff --git a/snapshots/TheCompactTest.json b/snapshots/TheCompactTest.json index 1c82737..78f112c 100644 --- a/snapshots/TheCompactTest.json +++ b/snapshots/TheCompactTest.json @@ -1,23 +1,23 @@ { "basicTransfer": "56955", - "basicWithdrawal": "59992", + "basicWithdrawal": "60014", "batchClaim": "112534", "batchClaimRegisteredWithDeposit": "112534", "batchClaimRegisteredWithDepositWithWitness": "113359", "batchClaimWithWitness": "113353", - "batchDepositAndRegisterViaPermit2": "222147", - "batchDepositAndRegisterWithWitnessViaPermit2": "222125", - "batchTransfer": "81344", - "batchWithdrawal": "100137", + "batchDepositAndRegisterViaPermit2": "222176", + "batchDepositAndRegisterWithWitnessViaPermit2": "222154", + "batchTransfer": "81366", + "batchWithdrawal": "100115", "claim": "57062", "claimAndWithdraw": "73520", "claimWithWitness": "59493", - "depositAndRegisterViaPermit2": "124451", + "depositAndRegisterViaPermit2": "124480", "depositBatchSingleERC20": "68138", "depositBatchSingleNative": "28441", "depositBatchViaPermit2NativeAndERC20": "129839", "depositBatchViaPermit2SingleERC20": "104993", - "depositERC20AndURI": "67320", + "depositERC20AndURI": "67298", "depositERC20Basic": "67390", "depositERC20ViaPermit2AndURI": "98471", "depositETHAndURI": "26776", @@ -25,17 +25,17 @@ "depositRegisterFor": "529", "qualifiedBatchClaim": "114222", "qualifiedBatchClaimWithWitness": "113760", - "qualifiedClaim": "60450", + "qualifiedClaim": "60428", "qualifiedClaimWithWitness": "59098", "qualifiedSplitBatchClaim": "141574", "qualifiedSplitBatchClaimWithWitness": "141640", "qualifiedSplitClaim": "87065", "qualifiedSplitClaimWithWitness": "87540", - "register": "25379", + "register": "25401", "splitBatchClaim": "140876", "splitBatchClaimWithWitness": "140837", "splitBatchTransfer": "110696", - "splitBatchWithdrawal": "140361", + "splitBatchWithdrawal": "140383", "splitClaim": "86839", "splitClaimWithWitness": "86320", "splitTransfer": "82570", diff --git a/src/TheCompact.sol b/src/TheCompact.sol index 80d0021..6b1629e 100644 --- a/src/TheCompact.sol +++ b/src/TheCompact.sol @@ -48,13 +48,13 @@ contract TheCompact is ITheCompact, ERC6909, TheCompactLogic { function depositAndRegisterFor(address recipient, address token, address allocator, ResetPeriod resetPeriod, Scope scope, uint256 amount, address arbiter, uint256 nonce, uint256 expires) external returns (uint256 id) { id = _performCustomERC20Deposit(token, allocator, resetPeriod, scope, amount, recipient); - _registerUsingClaim(recipient, id, amount, arbiter, nonce, expires); + _registerUsingClaim(recipient, id, amount, arbiter, nonce, expires, resetPeriod); } function depositAndRegisterFor(address recipient, address token, address allocator, ResetPeriod resetPeriod, Scope scope, uint256 amount, address arbiter, uint256 nonce, uint256 expires, bytes32 typehash, bytes32 witness) external returns (uint256 id) { id = _performCustomERC20Deposit(token, allocator, resetPeriod, scope, amount, recipient); - _registerUsingClaimWithWitness(recipient, id, amount, arbiter, nonce, expires, typehash, witness); + _registerUsingClaimWithWitness(recipient, id, amount, arbiter, nonce, expires, typehash, witness, resetPeriod); } function deposit(address allocator, ResetPeriod resetPeriod, Scope scope, address recipient) external payable returns (uint256) { @@ -77,19 +77,18 @@ contract TheCompact is ITheCompact, ERC6909, TheCompactLogic { return _registerBatch(claimHashesAndTypehashes, duration); } - function depositAndRegisterFor(address recipient, uint256[2][] calldata idsAndAmounts, address arbiter, uint256 nonce, uint256 expires) external { + function depositAndRegisterFor(address recipient, uint256[2][] calldata idsAndAmounts, address arbiter, uint256 nonce, uint256 expires, ResetPeriod resetPeriod) external { _processBatchDeposit(idsAndAmounts, recipient); - _registerUsingBatchClaim(recipient, idsAndAmounts, arbiter, nonce, expires); + _registerUsingBatchClaim(recipient, idsAndAmounts, arbiter, nonce, expires, resetPeriod); } - function depositAndRegisterFor(address recipient, uint256[2][] calldata idsAndAmounts, address arbiter, uint256 nonce, uint256 expires, bytes32 typehash, bytes32 witness) external { + function depositAndRegisterFor(address recipient, uint256[2][] calldata idsAndAmounts, address arbiter, uint256 nonce, uint256 expires, bytes32 typehash, bytes32 witness, ResetPeriod resetPeriod) external { _processBatchDeposit(idsAndAmounts, recipient); - _registerUsingBatchClaimWithWitness(recipient, idsAndAmounts, arbiter, nonce, expires, typehash, witness); + _registerUsingBatchClaimWithWitness(recipient, idsAndAmounts, arbiter, nonce, expires, typehash, witness, resetPeriod); } - function deposit( address token, uint256, // amount diff --git a/src/lib/HashLib.sol b/src/lib/HashLib.sol index d16240a..746b177 100644 --- a/src/lib/HashLib.sol +++ b/src/lib/HashLib.sol @@ -797,7 +797,7 @@ library HashLib { } //// Registration Hashes //// - function toFlatClaimMessageHash(address sponsor, uint256 id, uint256 amount, address arbiter, uint256 nonce, uint256 expires) internal pure returns(bytes32 messageHash) { + function toFlatClaimMessageHash(address sponsor, uint256 tokenId, uint256 amount, address arbiter, uint256 nonce, uint256 expires) internal pure returns(bytes32 messageHash) { assembly ("memory-safe") { // Retrieve the free memory pointer; memory will be left dirtied. let m := mload(0x40) @@ -807,14 +807,14 @@ library HashLib { mstore(add(m, 0x40), sponsor) mstore(add(m, 0x60), nonce) mstore(add(m, 0x80), expires) - mstore(add(m, 0xa0), id) + mstore(add(m, 0xa0), tokenId) mstore(add(m, 0xc0), amount) // Derive the message hash from the prepared data. messageHash := keccak256(m, 0xe0) } } - function toFlatMessageHashWithWitness(address sponsor, uint256 id, uint256 amount, address arbiter, uint256 nonce, uint256 expires, bytes32 typehash, bytes32 witness) internal pure returns(bytes32 messageHash) { + function toFlatMessageHashWithWitness(address sponsor, uint256 tokenId, uint256 amount, address arbiter, uint256 nonce, uint256 expires, bytes32 typehash, bytes32 witness) internal pure returns(bytes32 messageHash) { assembly ("memory-safe") { // Retrieve the free memory pointer; memory will be left dirtied. let m := mload(0x40) @@ -824,7 +824,7 @@ library HashLib { mstore(add(m, 0x40), sponsor) mstore(add(m, 0x60), nonce) mstore(add(m, 0x80), expires) - mstore(add(m, 0xa0), id) + mstore(add(m, 0xa0), tokenId) mstore(add(m, 0xc0), amount) mstore(add(m, 0xe0), witness) // Derive the message hash from the prepared data. diff --git a/src/lib/RegistrationLib.sol b/src/lib/RegistrationLib.sol index 73fdcef..20f37fb 100644 --- a/src/lib/RegistrationLib.sol +++ b/src/lib/RegistrationLib.sol @@ -71,35 +71,6 @@ library RegistrationLib { } } - /** - * @notice Helper function for registerCompactWithSpecificDuration, if the expiry is known - * but the duration is not. Is less efficient than registerCompactWithSpecificDuration - * @dev Expires will be converted into a duration by subtracting the current timestamp from it - * If the current timestamp is greater than the expires, the call will revert. - * @param sponsor The account registering the claim hash. - * @param claimHash A bytes32 hash derived from the details of the compact. - * @param typehash The EIP-712 typehash associated with the claim hash. - * @param expires Timestamp when the claim will expire. - */ - function registerCompactWithSpecificExpiry(address sponsor, bytes32 claimHash, bytes32 typehash, uint256 expires) internal { - uint256 duration; - assembly ("memory-safe") { - // Compute new expiration based on current timestamp and supplied duration. - // This may overflow. We check overflow during InvalidRegistrationDuration. - duration := sub(expires, timestamp()) - - // Ensure new expiration does not exceed current and duration does not exceed 30 days. - // If duration > expires AND duration = expires - timestmap > expires, then overflow. - if gt(duration, expires) { - // revert InvalidRegistrationDuration(uint256 duration) - mstore(0, 0x1f9a96f4) - mstore(0x20, duration) - revert(0x1c, 0x24) - } - } - registerCompactWithSpecificDuration(sponsor, claimHash, typehash, duration); - } - /** * @notice Internal function for registering a claim hash with a duration specified as a * ResetPeriod enum value. diff --git a/src/lib/RegistrationLogic.sol b/src/lib/RegistrationLogic.sol index 6d7073c..174bd92 100644 --- a/src/lib/RegistrationLogic.sol +++ b/src/lib/RegistrationLogic.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.27; import { RegistrationLib } from "./RegistrationLib.sol"; import { HashLib } from "./HashLib.sol"; import { COMPACT_TYPEHASH, BATCH_COMPACT_TYPEHASH } from "../types/EIP712Types.sol"; +import { ResetPeriod } from "../types/ResetPeriod.sol"; /** * @title RegistrationLogic @@ -63,23 +64,89 @@ contract RegistrationLogic { return sponsor.toRegistrationExpiration(claimHash, typehash); } - function _registerUsingClaim(address sponsor, uint256 id, uint256 amount, address arbiter, uint256 nonce, uint256 expires) internal { - bytes32 claimhash = HashLib.toFlatClaimMessageHash(sponsor, id, amount, arbiter, nonce, expires); - sponsor.registerCompactWithSpecificExpiry(claimhash, COMPACT_TYPEHASH, expires); + //// Registration of specific claims //// + + /** + * @notice Internal function to register a specific claim by its components. + * @dev Constructs and registers the compact that consists exactly of the provided + * arguments. + * @param sponsor Account that the claim should be registered for. + * @param tokenId Identifier for the associated token & lock. + * @param amount Claim's assocaited number of tokens. + * @param arbiter Account verifying and initiating the settlement of the claim. + * @param nonce Nonce to register the claim at. The nonce is not checked to be + * unspent + * @param expires Timestamp when the claim expires. Not to be confused with the reset + * time of the compact. + * @param resetPeriod Duration after which the resource locks can be reset once forced + * withdrawals are initiated. + */ + function _registerUsingClaim(address sponsor, uint256 tokenId, uint256 amount, address arbiter, uint256 nonce, uint256 expires, ResetPeriod resetPeriod) internal { + bytes32 claimhash = HashLib.toFlatClaimMessageHash(sponsor, tokenId, amount, arbiter, nonce, expires); + sponsor.registerCompact(claimhash, COMPACT_TYPEHASH, resetPeriod); } - function _registerUsingClaimWithWitness(address sponsor, uint256 id, uint256 amount, address arbiter, uint256 nonce, uint256 expires, bytes32 typehash, bytes32 witness) internal { - bytes32 claimhash = HashLib.toFlatMessageHashWithWitness(sponsor, id, amount, arbiter, nonce, expires, typehash, witness); - sponsor.registerCompactWithSpecificExpiry(claimhash, typehash, expires); + /** + * @notice Internal function to register a claim with witness by its components. + * @dev Constructs and registers the compact that consists exactly of the provided + * arguments. + * @param sponsor Account that the claim should be registered for. + * @param tokenId Identifier for the associated token & lock. + * @param amount Claim's assocaited number of tokens. + * @param arbiter Account verifying and initiating the settlement of the claim. + * @param nonce Nonce to register the claim at. The nonce is not checked to be + * unspent + * @param expires Timestamp when the claim expires. Not to be confused with the reset + * time of the compact. + * @param typehash Typehash of the entire compact. Including the subtypes of the + * witness + * @param witness EIP712 structured hash of witness. + * @param resetPeriod Duration after which the resource locks can be reset once forced + * withdrawals are initiated. + */ + function _registerUsingClaimWithWitness(address sponsor, uint256 tokenId, uint256 amount, address arbiter, uint256 nonce, uint256 expires, bytes32 typehash, bytes32 witness, ResetPeriod resetPeriod) internal { + bytes32 claimhash = HashLib.toFlatMessageHashWithWitness(sponsor, tokenId, amount, arbiter, nonce, expires, typehash, witness); + sponsor.registerCompact(claimhash, typehash, resetPeriod); } - function _registerUsingBatchClaim(address sponsor, uint256[2][] calldata idsAndAmounts, address arbiter, uint256 nonce, uint256 expires) internal { + /** + * @notice Internal function to register a batch claim by its components. + * @dev Constructs and registers the compact that consists exactly of the provided + * arguments. + * @param sponsor Account that the claim should be registered for. + * @param idsAndAmounts Ids and amounts associated with the to be registered claim. + * @param arbiter Account verifying and initiating the settlement of the claim. + * @param nonce Nonce to register the claim at. The nonce is not checked to be + * unspent + * @param expires Timestamp when the claim expires. Not to be confused with the + * reset time of the compact. + * @param resetPeriod Duration after which the resource locks can be reset once forced + * withdrawals are initiated. + */ + function _registerUsingBatchClaim(address sponsor, uint256[2][] calldata idsAndAmounts, address arbiter, uint256 nonce, uint256 expires, ResetPeriod resetPeriod) internal { bytes32 claimhash = HashLib.toFlatBatchMessageHash(sponsor, idsAndAmounts, arbiter, nonce, expires); - sponsor.registerCompactWithSpecificExpiry(claimhash, BATCH_COMPACT_TYPEHASH, expires); + sponsor.registerCompact(claimhash, BATCH_COMPACT_TYPEHASH, resetPeriod); } - function _registerUsingBatchClaimWithWitness(address sponsor, uint256[2][] calldata idsAndAmounts, address arbiter, uint256 nonce, uint256 expires, bytes32 typehash, bytes32 witness) internal { + /** + * @notice Internal function to register a batch claim with witness by its components. + * @dev Constructs and registers the compact that consists exactly of the provided + * arguments. + * @param sponsor Account that the claim should be registered for. + * @param idsAndAmounts Ids and amounts associated with the to be registered claim. + * @param arbiter Account verifying and initiating the settlement of the claim. + * @param nonce Nonce to register the claim at. The nonce is not checked to be + * unspent + * @param expires Timestamp when the claim expires. Not to be confused with the + * reset time of the compact. + * @param typehash Typehash of the entire compact. Including the subtypes of the + * witness + * @param witness EIP712 structured hash of witness. + * @param resetPeriod Duration after which the resource locks can be reset once forced + * withdrawals are initiated. + */ + function _registerUsingBatchClaimWithWitness(address sponsor, uint256[2][] calldata idsAndAmounts, address arbiter, uint256 nonce, uint256 expires, bytes32 typehash, bytes32 witness, ResetPeriod resetPeriod) internal { bytes32 claimhash = HashLib.toFlatBatchClaimWithWitnessMessageHash(sponsor, idsAndAmounts, arbiter, nonce, expires, typehash, witness); - sponsor.registerCompactWithSpecificExpiry(claimhash, typehash, expires); + sponsor.registerCompact(claimhash, typehash, resetPeriod); } } diff --git a/test/TheCompact.t.sol b/test/TheCompact.t.sol index 7842359..70c382e 100644 --- a/test/TheCompact.t.sol +++ b/test/TheCompact.t.sol @@ -1174,7 +1174,7 @@ contract TheCompactTest is Test { (bool isActive, uint256 expiresAt) = theCompact.getRegistrationStatus(swapper, claimHash, typehash); assert(isActive); - assertEq(expiresAt, block.timestamp + 1000); + assertEq(expiresAt, block.timestamp + 10 * 60); bytes memory sponsorSignature = "";