-
Notifications
You must be signed in to change notification settings - Fork 14
feat: Enable deposit and match orders in a single tx #316
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
gfournierPro
merged 43 commits into
chore/solidity-v8
from
feat/deposit-matchOrder-via-receiveApproval
Nov 10, 2025
Merged
Changes from all commits
Commits
Show all changes
43 commits
Select commit
Hold shift + click to select a range
394908b
feat: Update Solidity version to ^0.8.0 and refactor contracts for im…
gfournierPro 68c1e89
feat: Enhance IexecEscrowTokenFacet with approval event and order mat…
gfournierPro 23a067f
feat: Add error and event definitions for approval handling in IexecE…
gfournierPro fc6926b
feat: Add ApprovalReceivedAndMatched event and refactor error handlin…
gfournierPro 0ae822a
Merge branch 'main' into feat/deposit-matchOrder-via-receiveApproval
gfournierPro fb844af
feat: update ABI definitions and remove deprecated events
gfournierPro 7f08cf3
feat: implement encodeOrders function for ABI encoding in receiveAppr…
gfournierPro 3517bf0
refactor: reorganize order handling functions in receiveApproval tests
gfournierPro 47ecf74
fix: clarify return value description in _matchOrdersAfterDeposit fun…
gfournierPro 0b8ed3e
Merge branch 'main' into feat/deposit-matchOrder-via-receiveApproval
gfournierPro bd2adf1
Merge branch 'chore/solidity-v8' into feat/deposit-matchOrder-via-rec…
gfournierPro 0e57654
chore: remove deprecated ABI files from the project
gfournierPro fda1c38
style: standardize code formatting and improve readability across mul…
gfournierPro 6ca7c61
fix: solidity docs
gfournierPro 921df75
Merge branch 'fix/format-sc' into feat/deposit-matchOrder-via-receive…
gfournierPro 0c661b3
refactor: remove duplicate import statements in IexecEscrowTokenFacet…
gfournierPro d9b56ba
docs: enhance receiveApproval function documentation with usage patte…
gfournierPro b51807f
test: remove describe.only to enable all tests in IexecEscrowToken.re…
gfournierPro ad0130f
feat: add human-readable ABIs for ERC20, ERC721, and utility contracts
gfournierPro 689e1c3
Merge branch 'fix/format-sc' into feat/deposit-matchOrder-via-receive…
gfournierPro ec05830
fix: correct typo in error message for transferFrom in _deposit function
gfournierPro 22e3b3e
docs: update receiveApproval function documentation for clarity and a…
gfournierPro be65435
refactor: remove ApprovalReceivedAndMatched event and related references
gfournierPro 648078e
refactor: move IexecInterfaceToken documentation to the correct section
gfournierPro f8681d3
refactor: rename _matchOrdersAfterDeposit to _decodeDataAndMatchOrder…
gfournierPro b229dc5
refactor: remove human-readable ABIs for unused contracts
gfournierPro 0e656ee
Merge branch 'fix/format-sc' into feat/deposit-matchOrder-via-receive…
gfournierPro 137dd04
refactor: update delegatecall usage for safety and clarify function d…
gfournierPro c49a93e
Merge branch 'chore/solidity-v8' into fix/format-sc
gfournierPro 69ebbcd
fix: docs
gfournierPro f21473b
Merge branch 'fix/format-sc' into feat/deposit-matchOrder-via-receive…
gfournierPro 024675e
feat: enhance receiveApproval function with order matching capabiliti…
gfournierPro b06e552
docs: enhance receiveApproval function documentation with important n…
gfournierPro 64d8d80
fix: update deposit function to override and adjust balance verificat…
gfournierPro fc99890
Merge branch 'chore/solidity-v8' into feat/deposit-matchOrder-via-rec…
gfournierPro 4917773
docs: add important notes on order matching and deal cost calculation…
gfournierPro 6e36267
refactor: remove gas comparison test for order matching
gfournierPro 2e32246
fix: update approval process to use approveAndCall for existing balan…
gfournierPro 14e1614
feat: add TODO to consider making sponsor origin a variable in match …
gfournierPro c2397f9
feat: add ReceiveApprovalTestHelper contract to simulate silent failu…
gfournierPro 5fee6ac
fix: update copyright year in ReceiveApprovalTestHelper contract
gfournierPro b6a04d5
refactor: simplify _decodeDataAndMatchOrders by removing unused dealI…
gfournierPro da0c7bb
refactor: update comments in IexecEscrowTokenFacet for clarity on dep…
gfournierPro File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -227,7 +227,7 @@ | |
| }, | ||
| { | ||
| "internalType": "bytes", | ||
| "name": "", | ||
| "name": "data", | ||
| "type": "bytes" | ||
| } | ||
| ], | ||
|
|
||
3 changes: 3 additions & 0 deletions
3
...abis/contracts/tools/testing/ReceiveApprovalTestHelper.sol/ReceiveApprovalTestHelper.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| [ | ||
| "function matchOrders(tuple(address,uint256,uint256,bytes32,address,address,address,bytes32,bytes),tuple(address,uint256,uint256,bytes32,address,address,address,bytes32,bytes),tuple(address,uint256,uint256,bytes32,uint256,uint256,address,address,address,bytes32,bytes),tuple(address,uint256,address,uint256,address,uint256,address,uint256,bytes32,uint256,uint256,address,address,string,bytes32,bytes)) pure returns (bytes32)" | ||
| ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,8 @@ import {IexecERC20Core} from "./IexecERC20Core.sol"; | |
| import {FacetBase} from "./FacetBase.sol"; | ||
| import {IexecEscrowToken} from "../interfaces/IexecEscrowToken.sol"; | ||
| import {IexecTokenSpender} from "../interfaces/IexecTokenSpender.sol"; | ||
| import {IexecPoco1} from "../interfaces/IexecPoco1.sol"; | ||
| import {IexecLibOrders_v5} from "../libs/IexecLibOrders_v5.sol"; | ||
| import {PocoStorageLib} from "../libs/PocoStorageLib.sol"; | ||
|
|
||
| contract IexecEscrowTokenFacet is IexecEscrowToken, IexecTokenSpender, FacetBase, IexecERC20Core { | ||
|
|
@@ -64,23 +66,121 @@ contract IexecEscrowTokenFacet is IexecEscrowToken, IexecTokenSpender, FacetBase | |
| return delta; | ||
| } | ||
|
|
||
| // Token Spender (endpoint for approveAndCallback calls to the proxy) | ||
| /*************************************************************************** | ||
| * Token Spender: Atomic Deposit+Match * | ||
| ***************************************************************************/ | ||
|
|
||
| /** | ||
| * @notice Receives approval, deposit and optionally matches orders in one transaction | ||
| * | ||
| * Usage patterns: | ||
| * 1. Simple deposit: RLC.approveAndCall(escrow, amount, "") | ||
| * 2. Deposit + match: RLC.approveAndCall(escrow, amount, encodedOrders) | ||
| * | ||
| * The `data` parameter should be ABI-encoded orders if matching is desired: | ||
| * abi.encode(appOrder, datasetOrder, workerpoolOrder, requestOrder) | ||
| * | ||
| * @dev Important notes: | ||
| * - Match orders sponsoring is NOT supported. The requester (sender) always pays for the deal. | ||
| * - Clients must compute the exact deal cost and deposit the right amount for the deal to be matched. | ||
| * The deal cost = (appPrice + datasetPrice + workerpoolPrice) * volume. | ||
| * - If insufficient funds are deposited, the match will fail. | ||
| * | ||
| * @param sender The address that approved tokens (must be requester if matching) | ||
| * @param amount Amount of tokens approved and to be deposited | ||
| * @param token Address of the token (must be RLC) | ||
| * @param data Optional: ABI-encoded orders for matching | ||
| * @return success True if operation succeeded | ||
| * | ||
| * | ||
| * @custom:example | ||
| * ```solidity | ||
| * // Compute deal cost | ||
| * uint256 dealCost = (appPrice + datasetPrice + workerpoolPrice) * volume; | ||
| * | ||
| * // Encode orders | ||
| * bytes memory data = abi.encode(appOrder, datasetOrder, workerpoolOrder, requestOrder); | ||
| * | ||
| * // One transaction does it all | ||
| * RLC(token).approveAndCall(iexecProxy, dealCost, data); | ||
| * ``` | ||
| */ | ||
| function receiveApproval( | ||
| address sender, | ||
| uint256 amount, | ||
| address token, | ||
| bytes calldata | ||
| bytes calldata data | ||
| ) external override returns (bool) { | ||
| PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); | ||
| require(token == address($.m_baseToken), "wrong-token"); | ||
| _deposit(sender, amount); | ||
| _mint(sender, amount); | ||
| if (data.length > 0) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have two choices here:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will check that on a later PR |
||
| _decodeDataAndMatchOrders(sender, data); | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| /****************************************************************************** | ||
| * Token Spender: Atomic Deposit+Match if used with RLC.approveAndCall * | ||
gfournierPro marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| *****************************************************************************/ | ||
|
|
||
gfournierPro marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| /** | ||
| * @dev Internal function to match orders after deposit | ||
| * @param sender The user who deposited (must be the requester) | ||
| * @param data ABI-encoded orders | ||
| */ | ||
| function _decodeDataAndMatchOrders(address sender, bytes calldata data) internal { | ||
| // Decode the orders from calldata | ||
| ( | ||
| IexecLibOrders_v5.AppOrder memory apporder, | ||
| IexecLibOrders_v5.DatasetOrder memory datasetorder, | ||
| IexecLibOrders_v5.WorkerpoolOrder memory workerpoolorder, | ||
| IexecLibOrders_v5.RequestOrder memory requestorder | ||
| ) = abi.decode( | ||
| data, | ||
| ( | ||
| IexecLibOrders_v5.AppOrder, | ||
| IexecLibOrders_v5.DatasetOrder, | ||
| IexecLibOrders_v5.WorkerpoolOrder, | ||
| IexecLibOrders_v5.RequestOrder | ||
| ) | ||
| ); | ||
|
|
||
| // Validate that sender is the requester | ||
| if (requestorder.requester != sender) revert("caller-must-be-requester"); | ||
Le-Caignec marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // Call matchOrders on the IexecPoco1 facet through the diamond | ||
| // Using delegatecall for safety: preserves msg.sender context (RLC address in this case) | ||
| // Note: matchOrders doesn't use msg.sender, but delegatecall is safer | ||
| // in case the implementation changes in the future | ||
| (bool success, bytes memory result) = address(this).delegatecall( | ||
| abi.encodeWithSelector( | ||
| IexecPoco1.matchOrders.selector, | ||
| apporder, | ||
| datasetorder, | ||
| workerpoolorder, | ||
| requestorder | ||
| ) | ||
| ); | ||
|
|
||
| // Handle failure and bubble up revert reason | ||
| if (!success) { | ||
| if (result.length > 0) { | ||
| // Decode and revert with the original error | ||
| assembly { | ||
| let returndata_size := mload(result) | ||
| revert(add(result, 32), returndata_size) | ||
| } | ||
| } else { | ||
| revert("receive-approval-failed"); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| function _deposit(address from, uint256 amount) internal { | ||
| PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); | ||
| require($.m_baseToken.transferFrom(from, address(this), amount), "failled-transferFrom"); | ||
| require($.m_baseToken.transferFrom(from, address(this), amount), "failed-transferFrom"); | ||
| } | ||
|
|
||
| function _withdraw(address to, uint256 amount) internal { | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| // SPDX-FileCopyrightText: 2025 IEXEC BLOCKCHAIN TECH <[email protected]> | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| pragma solidity ^0.8.0; | ||
|
|
||
| import {IexecLibOrders_v5} from "../../libs/IexecLibOrders_v5.sol"; | ||
|
|
||
| /** | ||
| * @title ReceiveApprovalTestHelper | ||
| * @notice Helper contract to test edge cases in receiveApproval function | ||
| * @dev This contract simulates a facet that fails silently (no error data) | ||
| */ | ||
| contract ReceiveApprovalTestHelper { | ||
| /** | ||
| * @notice Mock matchOrders function that fails without returning error data | ||
| * @dev Uses assembly to revert without data, simulating the edge case where | ||
| * delegatecall fails and result.length == 0 | ||
| */ | ||
| function matchOrders( | ||
| IexecLibOrders_v5.AppOrder calldata, | ||
| IexecLibOrders_v5.DatasetOrder calldata, | ||
| IexecLibOrders_v5.WorkerpoolOrder calldata, | ||
| IexecLibOrders_v5.RequestOrder calldata | ||
| ) external pure returns (bytes32) { | ||
| // Revert without any error data | ||
| // This simulates: delegatecall fails with success=false and result.length=0 | ||
| assembly { | ||
| revert(0, 0) | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.