Skip to content

make progress on stack depth issues when running coverage #75

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Apr 16, 2025
12 changes: 12 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,15 @@ jobs:
id: test
env:
FORGE_SNAPSHOT_CHECK: true

- name: Run Forge coverage
run: |
forge coverage --report lcov
id: coverage

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./lcov.info
fail_ci_if_error: true
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Compiler files
cache/
out/
lcov.info

# Ignores development broadcast logs
!/broadcast
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

> :warning: This is an early-stage contract under active development; it has not yet been properly tested, reviewed, or audited.

> NOTE: this README is based on Version 0 of The Compact; it still needs to be updated for Version 1, which is currently under active development.

## Summary
The Compact is an ownerless ERC6909 contract that facilitates the voluntary formation (and, if necessary, eventual dissolution) of reusable resource locks.

Expand Down Expand Up @@ -35,8 +37,11 @@ $ git clone [email protected]:Uniswap/the-compact.git && cd the-compact
# install dependencies & libraries
$ forge install

# run basic tests
# run basic tests & gas snapshots
$ forge test

# run coverage & generate report
$ forge coverage --report lcov
```

## Usage
Expand Down
52 changes: 52 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
codecov:
require_ci_to_pass: yes

coverage:
precision: 2
round: down
range: "70...100"
status:
project:
default:
# basic
target: auto
threshold: 0%
base: auto
# advanced
branches: null
if_no_uploads: error
if_not_found: success
if_ci_failed: error
only_pulls: false
flags: null
paths: null
patch:
default:
# basic
target: auto
threshold: 0%
base: auto
# advanced
branches: null
if_no_uploads: error
if_not_found: success
if_ci_failed: error
only_pulls: false
flags: null
paths: null

parsers:
gcov:
branch_detection:
conditional: yes
loop: yes
method: no
macro: no

comment:
layout: "reach,diff,flags,files,footer"
behavior: default
require_changes: no
require_base: no
require_head: yes
branches: null
52 changes: 26 additions & 26 deletions snapshots/TheCompactTest.json
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
{
"batchClaimRegisteredWithDepositWithWitness": "145160",
"batchDepositAndRegisterWithWitnessViaPermit2": "219004",
"claim": "86514",
"claimAndWithdraw": "114496",
"depositAndRegisterViaPermit2": "123247",
"depositBatchSingleERC20": "66450",
"depositBatchSingleNative": "26935",
"depositBatchViaPermit2NativeAndERC20": "127573",
"depositBatchViaPermit2SingleERC20": "102735",
"depositERC20AndURI": "65883",
"depositERC20Basic": "65883",
"depositERC20ViaPermit2AndURI": "98371",
"depositETHAndURI": "25953",
"batchClaimRegisteredWithDepositWithWitness": "145278",
"batchDepositAndRegisterWithWitnessViaPermit2": "218447",
"claim": "86555",
"claimAndWithdraw": "114537",
"depositAndRegisterViaPermit2": "122980",
"depositBatchSingleERC20": "66488",
"depositBatchSingleNative": "26957",
"depositBatchViaPermit2NativeAndERC20": "127465",
"depositBatchViaPermit2SingleERC20": "102627",
"depositERC20AndURI": "65965",
"depositERC20Basic": "65965",
"depositERC20ViaPermit2AndURI": "97718",
"depositETHAndURI": "26019",
"depositETHBasic": "26177",
"depositRegisterFor": "78131",
"exogenousSplitBatchMultichainClaimWithWitness": "119870",
"exogenousSplitMultichainClaimWithWitness": "91532",
"qualified_basicTransfer": "59816",
"register": "24458",
"splitBatchClaimWithWitness": "145154",
"splitBatchMultichainClaimWithWitness": "92127",
"splitBatchTransfer": "117228",
"splitBatchWithdrawal": "146028",
"splitClaimWithWitness": "89649",
"splitMultichainClaimWithWitness": "90333",
"splitTransfer": "86967",
"splitWithdrawal": "95819"
"depositRegisterFor": "78197",
"exogenousSplitBatchMultichainClaimWithWitness": "120030",
"exogenousSplitMultichainClaimWithWitness": "91645",
"qualified_basicTransfer": "59904",
"register": "24502",
"splitBatchClaimWithWitness": "145278",
"splitBatchMultichainClaimWithWitness": "92279",
"splitBatchTransfer": "117294",
"splitBatchWithdrawal": "146094",
"splitClaimWithWitness": "89690",
"splitMultichainClaimWithWitness": "90402",
"splitTransfer": "87055",
"splitWithdrawal": "95907"
}
65 changes: 31 additions & 34 deletions src/TheCompact.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Scope } from "./types/Scope.sol";
import { ResetPeriod } from "./types/ResetPeriod.sol";
import { ForcedWithdrawalStatus } from "./types/ForcedWithdrawalStatus.sol";
import { EmissaryStatus } from "./types/EmissaryStatus.sol";
import { DepositDetails } from "./types/DepositDetails.sol";

import { TheCompactLogic } from "./lib/TheCompactLogic.sol";

Expand Down Expand Up @@ -139,39 +140,31 @@ contract TheCompact is ITheCompact, ERC6909, TheCompactLogic {
}

function deposit(
address token,
uint256, // amount
uint256, // nonce
uint256, // deadline
ISignatureTransfer.PermitTransferFrom calldata permit,
address, // depositor
bytes12, // lockTag
address recipient,
bytes calldata signature
) external returns (uint256) {
return _depositViaPermit2(token, recipient, signature);
return _depositViaPermit2(permit.permitted.token, recipient, signature);
}

function depositAndRegister(
address token,
uint256, // amount
uint256, // nonce
uint256, // deadline
ISignatureTransfer.PermitTransferFrom calldata permit,
address depositor, // also recipient
bytes12, // lockTag
bytes32 claimHash,
CompactCategory compactCategory,
CompactCategory, // compactCategory
string calldata witness,
bytes calldata signature
) external returns (uint256) {
return _depositAndRegisterViaPermit2(token, depositor, claimHash, compactCategory, witness, signature);
return _depositAndRegisterViaPermit2(permit.permitted.token, depositor, claimHash, witness, signature);
}

function deposit(
address, // depositor
ISignatureTransfer.TokenPermissions[] calldata permitted,
uint256, // nonce
uint256, // deadline
bytes12, // lockTag
DepositDetails calldata,
address recipient,
bytes calldata signature
) external payable returns (uint256[] memory) {
Expand All @@ -181,15 +174,13 @@ contract TheCompact is ITheCompact, ERC6909, TheCompactLogic {
function depositAndRegister(
address depositor,
ISignatureTransfer.TokenPermissions[] calldata permitted,
uint256, // nonce
uint256, // deadline
bytes12, // lockTag,
bytes32 claimHash,
CompactCategory compactCategory,
DepositDetails calldata,
bytes32, // claimHash
CompactCategory, // compactCategory
string calldata witness,
bytes calldata signature
) external payable returns (uint256[] memory) {
return _depositBatchAndRegisterViaPermit2(depositor, permitted, claimHash, compactCategory, witness, signature);
return _depositBatchAndRegisterViaPermit2(depositor, permitted, witness, signature);
}

function allocatedTransfer(SplitTransfer calldata transfer) external returns (bool) {
Expand Down Expand Up @@ -244,12 +235,14 @@ contract TheCompact is ITheCompact, ERC6909, TheCompactLogic {
claimHash =
HashLib.toFlatMessageHashWithWitness(sponsor, id, amount, arbiter, nonce, expires, typehash, witness);

// Initialize idsAndAmounts array.
uint256[2][] memory idsAndAmounts = new uint256[2][](1);
idsAndAmounts[0] = [id, amount];
{
// Initialize idsAndAmounts array.
uint256[2][] memory idsAndAmounts = new uint256[2][](1);
idsAndAmounts[0] = [id, amount];

// TOOD: support registering exogenous domain separators by passing notarized chainId
claimHash.hasValidSponsor(sponsor, sponsorSignature, _domainSeparator(), idsAndAmounts);
// TODO: support registering exogenous domain separators by passing notarized chainId?
claimHash.hasValidSponsor(sponsor, sponsorSignature, _domainSeparator(), idsAndAmounts);
}

sponsor.registerCompact(claimHash, typehash);
}
Expand All @@ -264,6 +257,19 @@ contract TheCompact is ITheCompact, ERC6909, TheCompactLogic {
bytes32 witness,
bytes calldata sponsorSignature
) external returns (bytes32 claimHash) {
_enforceConsistentAllocators(idsAndAmounts);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: We may be looping over idsAndAmounts twice in this function. Once in _enforceConsistentAllocators and once in .hasValidSponsor if the emissary is checked. Because of stack issues, I don't believe we want to fix.


claimHash = HashLib.toFlatBatchClaimWithWitnessMessageHash(
sponsor, idsAndAmounts, arbiter, nonce, expires, typehash, witness
);

// TOOD: support registering exogenous domain separators by passing notarized chainId
claimHash.hasValidSponsor(sponsor, sponsorSignature, _domainSeparator(), idsAndAmounts);

sponsor.registerCompact(claimHash, typehash);
}

function _enforceConsistentAllocators(uint256[2][] calldata idsAndAmounts) internal view {
// Retrieve the total number of IDs and amounts in the batch.
uint256 totalIds = idsAndAmounts.length;

Expand All @@ -288,15 +294,6 @@ contract TheCompact is ITheCompact, ERC6909, TheCompactLogic {
if (errorBuffer.asBool()) {
revert InconsistentAllocators();
}

claimHash = HashLib.toFlatBatchClaimWithWitnessMessageHash(
sponsor, idsAndAmounts, arbiter, nonce, expires, typehash, witness
);

// TOOD: support registering exogenous domain separators by passing notarized chainId
claimHash.hasValidSponsor(sponsor, sponsorSignature, _domainSeparator(), idsAndAmounts);

sponsor.registerCompact(claimHash, typehash);
}

function assignEmissary(bytes12 lockTag, address emissary) external returns (bool) {
Expand Down
42 changes: 11 additions & 31 deletions src/interfaces/ITheCompact.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Scope } from "../types/Scope.sol";
import { CompactCategory } from "../types/CompactCategory.sol";
import { ISignatureTransfer } from "permit2/src/interfaces/ISignatureTransfer.sol";
import { BasicTransfer, SplitTransfer } from "../types/Claims.sol";
import { DepositDetails } from "../types/DepositDetails.sol";

import { BatchTransfer, SplitBatchTransfer } from "../types/BatchClaims.sol";

Expand Down Expand Up @@ -274,21 +275,14 @@ interface ITheCompact {
* implementation details of the respective token. The Permit2 authorization signed by the
* depositor must contain a CompactDeposit witness containing the allocator, the reset period,
* the scope, and the intended recipient of the deposit.
* @param token The address of the ERC20 token to deposit.
* @param amount The amount of tokens to deposit.
* @param nonce The Permit2 nonce for the signature.
* @param deadline The timestamp until which the signature is valid.
* @param depositor The account signing the permit2 authorization and depositing the tokens.
* @param permit The permit data signed by the depositor.
* @param lockTag The lock tag containing allocator ID, reset period, and scope.
* @param recipient The address that will receive the corresponding the ERC6909 tokens.
* @param signature The Permit2 signature from the depositor authorizing the deposit.
* @return id The ERC6909 token identifier of the associated resource lock.
*/
function deposit(
address token,
uint256 amount,
uint256 nonce,
uint256 deadline,
ISignatureTransfer.PermitTransferFrom calldata permit,
address depositor,
bytes12 lockTag,
address recipient,
Expand All @@ -305,23 +299,17 @@ interface ITheCompact {
* signed by the depositor must contain an Activation witness containing the id of the resource
* lock and an associated Compact, BatchCompact, or MultichainCompact payload matching the
* specified compact category.
* @param token The address of the ERC20 token to deposit.
* @param amount The amount of tokens to deposit.
* @param nonce The Permit2 nonce for the signature.
* @param deadline The timestamp until which the signature is valid.
* @param permit The permit data signed by the depositor.
* @param depositor The account signing the permit2 authorization and depositing the tokens.
* @param lockTag The lock tag containing allocator ID, reset period, and scope.
* @param lockTag The lock tag containing allocator ID, reset period, and scope.
* @param claimHash A bytes32 hash derived from the details of the compact.
* @param compactCategory The category of the compact being registered (Compact, BatchCompact, or MultichainCompact).
* @param witness Additional data used in generating the claim hash.
* @param signature The Permit2 signature from the depositor authorizing the deposit.
* @return id The ERC6909 token identifier of the associated resource lock.
*/
function depositAndRegister(
address token,
uint256 amount,
uint256 nonce,
uint256 deadline,
ISignatureTransfer.PermitTransferFrom calldata permit,
address depositor,
bytes12 lockTag,
bytes32 claimHash,
Expand All @@ -342,20 +330,16 @@ interface ITheCompact {
* CompactDeposit witness containing the allocator, the reset period, the scope, and the
* intended recipient of the deposits.
* @param depositor The account signing the permit2 authorization and depositing the tokens.
* @param permitted Array of token permissions specifying the deposited tokens and amounts.
* @param nonce The Permit2 nonce for the signature.
* @param deadline The timestamp until which the signature is valid.
* @param lockTag The lock tag containing allocator ID, reset period, and scope.
* @param permitted The permit data signed by the depositor.
* @param details The details of the deposit.
* @param recipient The address that will receive the corresponding ERC6909 tokens.
* @param signature The Permit2 signature from the depositor authorizing the deposits.
* @return ids Array of ERC6909 token identifiers for the associated resource locks.
*/
function deposit(
address depositor,
ISignatureTransfer.TokenPermissions[] calldata permitted,
uint256 nonce,
uint256 deadline,
bytes12 lockTag,
DepositDetails calldata details,
address recipient,
bytes calldata signature
) external payable returns (uint256[] memory ids);
Expand All @@ -374,9 +358,7 @@ interface ITheCompact {
* specified compact category.
* @param depositor The account signing the permit2 authorization and depositing the tokens.
* @param permitted Array of token permissions specifying the deposited tokens and amounts.
* @param nonce The Permit2 nonce for the signature.
* @param deadline The timestamp until which the signature is valid.
* @param lockTag The lock tag containing allocator ID, reset period, and scope.
* @param details The details of the deposit.
* @param claimHash A bytes32 hash derived from the details of the compact.
* @param compactCategory The category of the compact being registered (Compact, BatchCompact, or MultichainCompact).
* @param witness Additional data used in generating the claim hash.
Expand All @@ -386,9 +368,7 @@ interface ITheCompact {
function depositAndRegister(
address depositor,
ISignatureTransfer.TokenPermissions[] calldata permitted,
uint256 nonce,
uint256 deadline,
bytes12 lockTag,
DepositDetails calldata details,
bytes32 claimHash,
CompactCategory compactCategory,
string calldata witness,
Expand Down
Loading
Loading