Skip to content

feat(Escrow): add custom buyer option #117

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

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from

Conversation

unknownunknown1
Copy link
Contributor

@unknownunknown1 unknownunknown1 commented Jun 25, 2025

PR-Codex overview

This PR introduces a new function createERC20TransactionCustomBuyer in the EscrowUniversal contract, allowing a custom buyer to create ERC20 transactions. It also updates the foundry.toml configuration and adds a corresponding test case.

Detailed summary

  • Added via_ir = true in foundry.toml.
  • Introduced createERC20TransactionCustomBuyer function in EscrowUniversal.sol.
  • The function allows specifying a custom buyer for ERC20 transactions.
  • Added a test function test_createERC20TransactionCustomBuyer in EscrowUniversal.t.sol to verify the new functionality.

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

Summary by CodeRabbit

  • New Features
    • Added the ability to create ERC20 escrow transactions with custom buyer and seller addresses.
  • Tests
    • Introduced new tests to verify ERC20 escrow transactions with explicitly specified buyer and seller addresses.
  • Chores
    • Updated configuration settings for improved contract compilation.

Copy link

netlify bot commented Jun 25, 2025

Deploy Preview for kleros-escrow-v2 ready!

Name Link
🔨 Latest commit 50110c1
🔍 Latest deploy log https://app.netlify.com/projects/kleros-escrow-v2/deploys/685bb11d11bafa00082c2851
😎 Deploy Preview https://deploy-preview-117--kleros-escrow-v2.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@unknownunknown1 unknownunknown1 requested a review from kemuru June 25, 2025 08:19
Copy link
Contributor

coderabbitai bot commented Jun 25, 2025

Walkthrough

A new function, createERC20TransactionCustomBuyer, was added to the EscrowUniversal contract, enabling explicit specification of buyer and seller addresses when creating ERC20 escrow transactions. Corresponding tests were implemented to verify this functionality. Additionally, the Foundry configuration was updated to enable the via_ir compilation option.

Changes

File(s) Change Summary
contracts/foundry.toml Added via_ir = true to the [profile.default] section.
contracts/src/EscrowUniversal.sol Added createERC20TransactionCustomBuyer function for ERC20 escrow transactions with custom buyer and seller addresses.
contracts/test/EscrowUniversal.t.sol Added test test_createERC20TransactionCustomBuyer to verify the new function's behavior.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant EscrowUniversal
    participant ERC20Token

    Caller->>ERC20Token: approve(EscrowUniversal, amount)
    Caller->>EscrowUniversal: createERC20TransactionCustomBuyer(amount, token, deadline, uri, buyer, seller)
    EscrowUniversal->>ERC20Token: transferFrom(Caller, EscrowUniversal, amount)
    EscrowUniversal-->>Caller: returns transactionID
    EscrowUniversal-->>All: emit ERC20TransactionCreated(transactionID, buyer, seller, ...)
Loading

Suggested reviewers

  • jaybuidl

Poem

A hop, a leap, a clever tweak—
Now buyers and sellers both can speak!
With custom addresses in escrow’s embrace,
Tokens are safe, each in their place.
Tests abound, and configs shine,
This bunny’s code is quite divine!
🐇✨


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
contracts/src/EscrowUniversal.sol (1)

189-217: Consider access control implications of custom buyer functionality.

The current implementation allows any caller to create a transaction with arbitrary buyer and seller addresses. This means:

  1. Unauthorized transaction creation: Anyone can create transactions assigning buyer/seller roles to any addresses
  2. Potential confusion: The buyer might not be aware a transaction was created on their behalf
  3. Token responsibility: The caller provides tokens but loses control to the designated buyer

Consider implementing one of these approaches:

Option 1: Require buyer authorization

mapping(address => mapping(address => bool)) public authorizedCreators;

function authorizeBuyerCreation(address _creator, bool _authorized) external {
    authorizedCreators[msg.sender][_creator] = _authorized;
}

// In createERC20TransactionCustomBuyer:
if (_buyer != msg.sender && !authorizedCreators[_buyer][msg.sender]) {
    revert UnauthorizedBuyerCreation();
}

Option 2: Restrict to specific roles

mapping(address => bool) public trustedCreators;

modifier onlyTrustedCreator() {
    if (!trustedCreators[msg.sender]) revert NotTrustedCreator();
    _;
}

// Add modifier to function
function createERC20TransactionCustomBuyer(...) external onlyTrustedCreator shouldNotExceedCap(_token, _amount) returns (uint256 transactionID) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 282a30d and 50110c1.

📒 Files selected for processing (3)
  • contracts/foundry.toml (1 hunks)
  • contracts/src/EscrowUniversal.sol (1 hunks)
  • contracts/test/EscrowUniversal.t.sol (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: Redirect rules - kleros-escrow-v2
  • GitHub Check: Header rules - kleros-escrow-v2
  • GitHub Check: Redirect rules - kleros-escrow-v2
  • GitHub Check: Header rules - kleros-escrow-v2
  • GitHub Check: Pages changed - kleros-escrow-v2
  • GitHub Check: Pages changed - kleros-escrow-v2
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (2)
contracts/foundry.toml (1)

5-5: Verify the necessity of enabling IR compilation.

The via_ir = true setting enables intermediate representation compilation mode. Please confirm whether this change is required for the new createERC20TransactionCustomBuyer functionality or if it addresses a specific compilation issue.

#!/bin/bash
# Check if there are any compilation issues without via_ir flag
cd contracts
# Temporarily remove via_ir setting
sed -i.bak 's/via_ir = true/# via_ir = true/' foundry.toml
# Try to compile
forge build 2>&1 | grep -E "(error|Error|ERROR)" || echo "Compilation successful without via_ir"
# Restore original
mv foundry.toml.bak foundry.toml
contracts/test/EscrowUniversal.t.sol (1)

420-424: Well-structured test with correct balance assertions.

The test correctly verifies that:

  • The escrow contract receives the tokens
  • The transaction creator (buyer) retains remaining balance
  • The custom buyer has no token balance (as expected since they didn't provide tokens)
  • All transaction fields are properly set

Comment on lines +189 to +217
function createERC20TransactionCustomBuyer(
uint256 _amount,
IERC20 _token,
uint256 _deadline,
string memory _transactionUri,
address payable _buyer,
address payable _seller
) external shouldNotExceedCap(_token, _amount) returns (uint256 transactionID) {
// Transfers token from sender wallet to contract. Note that the amount is provided by the caller, not by the buyer.
if (!_token.safeTransferFrom(msg.sender, address(this), _amount)) revert TokenTransferFailed();
Transaction storage transaction = transactions.push();
transaction.buyer = _buyer;
transaction.seller = _seller;
transaction.amount = _amount;
transaction.token = _token;
transaction.deadline = _deadline;

transactionID = transactions.length - 1;

emit ERC20TransactionCreated(
transactionID,
_transactionUri,
_buyer,
_seller,
_token,
_amount,
transaction.deadline
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add validation for custom buyer address and consider security implications.

The new function allows specifying a custom buyer address, which introduces several considerations:

  1. Zero address validation: The function should validate that _buyer is not the zero address
  2. Same address validation: Consider whether _buyer and _seller should be allowed to be the same address
  3. Documentation: The function lacks proper NatSpec documentation explaining the custom buyer functionality

Apply this diff to add necessary validations and documentation:

+    /// @dev Creates an ERC20 escrow transaction with custom buyer and seller addresses.
+    /// @param _amount The amount of tokens to be escrowed.
+    /// @param _token The ERC20 token contract.
+    /// @param _deadline The deadline for the transaction.
+    /// @param _transactionUri The URI for transaction metadata.
+    /// @param _buyer The address that will be set as the buyer (different from caller).
+    /// @param _seller The address that will be set as the seller.
+    /// @return transactionID The ID of the created transaction.
     function createERC20TransactionCustomBuyer(
         uint256 _amount,
         IERC20 _token,
         uint256 _deadline,
         string memory _transactionUri,
         address payable _buyer,
         address payable _seller
     ) external shouldNotExceedCap(_token, _amount) returns (uint256 transactionID) {
+        if (_buyer == address(0)) revert ZeroBuyerAddress();
+        if (_seller == address(0)) revert ZeroSellerAddress();
+        if (_buyer == _seller) revert BuyerAndSellerCannotBeSame();
         // Transfers token from sender wallet to contract. Note that the amount is provided by the caller, not by the buyer.

Also, add the corresponding error definitions at the top of the contract:

+    error ZeroBuyerAddress();
+    error ZeroSellerAddress();
+    error BuyerAndSellerCannotBeSame();
🤖 Prompt for AI Agents
In contracts/src/EscrowUniversal.sol around lines 189 to 217, the
createERC20TransactionCustomBuyer function lacks validation for the _buyer
address and proper documentation. Add a require statement to ensure _buyer is
not the zero address, and consider adding a check or comment regarding whether
_buyer and _seller can be the same address based on your security model. Also,
add NatSpec comments above the function to explain its purpose and parameters.
Finally, define any new error types used for validation at the top of the
contract.

Comment on lines +383 to +424
function test_createERC20TransactionCustomBuyer() public {
uint256 deadline = block.timestamp + txTimeout;
uint256 txId;
vm.prank(buyer);
vm.expectEmit(true, true, true, true);
// Pay a bit less to differ between tests
emit ERC20TransactionCreated(txId, txUri, other, seller, escrowToken, 0.4 ether, deadline);
escrow.createERC20TransactionCustomBuyer(0.4 ether, escrowToken, deadline, txUri, payable(other), payable(seller));

(
address escrowBuyer,
address escrowSeller,
uint256 amount,
uint256 settlementBuyer,
uint256 settlementSeller,
uint256 escrowdeadline,
uint256 disputeId,
uint256 buyerFee,
uint256 sellerFee,
uint256 lastFeePaymentTime,
Status status,
IERC20 token
) = escrow.transactions(txId);

assertEq(escrowBuyer, other, "Wrong custom buyer address");
assertEq(escrowSeller, seller, "Wrong seller address");
assertEq(amount, 0.4 ether, "Wrong escrow amount");
assertEq(settlementBuyer, 0, "settlementBuyer should be 0");
assertEq(settlementSeller, 0, "settlementSeller should be 0");
assertEq(escrowdeadline, block.timestamp + 1000, "Wrong deadline");
assertEq(disputeId, 0, "disputeId should be 0");
assertEq(sellerFee, 0, "sellerFee should be 0");
assertEq(lastFeePaymentTime, 0, "lastFeePaymentTime should be 0");
assertEq(uint256(status), uint256(Status.NoDispute), "Wrong status");
assertEq(address(token), address(escrowToken), "Wrong token address");
assertEq(escrow.getTransactionCount(), 1, "Wrong transaction count");

assertEq(escrowToken.balanceOf(address(escrow)), 0.4 ether, "Wrong token balance of the escrow");
assertEq(escrowToken.balanceOf(buyer), 0.6 ether, "Wrong token balance of buyer"); // tx creator
assertEq(escrowToken.balanceOf(seller), 0, "Balance of seller should be 0");
assertEq(escrowToken.balanceOf(other), 0, "Balance of custom buyer should be 0"); // custom buyer did not have balance of his own
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance test coverage for edge cases and security scenarios.

The test covers the basic happy path but lacks coverage for important edge cases:

Add these additional test cases to ensure comprehensive coverage:

function test_createERC20TransactionCustomBuyer_zeroAddresses() public {
    uint256 deadline = block.timestamp + txTimeout;
    
    // Test zero buyer address
    vm.expectRevert(IEscrow.ZeroBuyerAddress.selector);
    vm.prank(buyer);
    escrow.createERC20TransactionCustomBuyer(
        0.4 ether, 
        escrowToken, 
        deadline, 
        txUri, 
        payable(address(0)), 
        payable(seller)
    );
    
    // Test zero seller address
    vm.expectRevert(IEscrow.ZeroSellerAddress.selector);
    vm.prank(buyer);
    escrow.createERC20TransactionCustomBuyer(
        0.4 ether, 
        escrowToken, 
        deadline, 
        txUri, 
        payable(other), 
        payable(address(0))
    );
}

function test_createERC20TransactionCustomBuyer_sameBuyerSeller() public {
    uint256 deadline = block.timestamp + txTimeout;
    
    vm.expectRevert(IEscrow.BuyerAndSellerCannotBeSame.selector);
    vm.prank(buyer);
    escrow.createERC20TransactionCustomBuyer(
        0.4 ether, 
        escrowToken, 
        deadline, 
        txUri, 
        payable(other), 
        payable(other)
    );
}
🤖 Prompt for AI Agents
In contracts/test/EscrowUniversal.t.sol around lines 383 to 424, the existing
test only covers the basic successful scenario for
createERC20TransactionCustomBuyer. To improve test coverage and security, add
two new test functions: one to check that the function reverts when the buyer or
seller address is zero, and another to verify it reverts when the buyer and
seller addresses are the same. Use vm.expectRevert with the appropriate error
selectors before calling createERC20TransactionCustomBuyer with these invalid
inputs to ensure the contract correctly handles these edge cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant