Jincubator Limit Order Protocol: Unite Defi (2025)
Unite Defi 2025 Jincubator 1inch Tycho NoLiquidity Swap
Jincubator Unite Defi Overview
Jincbuator is a research and development lab focusing on Solving, Arbitrage and Capital Efficient
No Liquidity Solving Walkthrough
The following Actions are Taken
- Mary has one ETH
- Chainlink Oracle has 1ETH = 2000DAI
- Mary creates a an order 1ETH for 2000DAI
- Tabatha using Tycho finds Uniswap V2 will swap 1ETH for 2018DAI
- Tabatha Takes the Order
- Order Settles
- *This uses a modified version of 1inch Limit Order Protocol which allows TychoSwapExecutor to settle the Makers Funds
- **Mary approves 1ETH to be used by Limit-Order-Protocol (and Tycho Swap Router)
- **Mary’s 1ETH is used for the swap - No Liquidity is provided by Tabatha - Transaction reverts if < 2000 DAI is returned
- ***Taking and Settling the order is an atomic transaction integrating TychoSwapExecutor.sol as a TakerInteraction in LimitOrderProtocol.sol
Action | Mary Maker | Limit Order Protocol | Tabatha Tycho Taker | Jincubator Protocol | Tycho Simulation |
---|---|---|---|---|---|
1 | 1 ETH | ||||
2 | 1 ETH | ||||
3 | 1ETH | 1ETH* | OrderCalculator.sol integrates price oracles for creating spread orders | ||
4 | 1ETH | 1ETH* | Tycho Indexing and Simulation (Off Chain Price Discovery) | ||
5 | 2018DAI** | TychoExecutor.sol executes the trade on UniswapV3 | TychoRouter is called by TychoSwapRouter to execute the trade | ||
6 | 200DAI | 18DAI | LimitOrderProtocol.sol sends Mary 2000 DAI from Tabatha | ||
Jincubator Limit Order Protocol
This protocol implements four key enhancements to the 1inch Limit Order Protocol:
- Enhanced Swap Execution: TychoSwapExecutor.sol integrates Tycho Execution to enable complex swaps across multiple DEXs without upfront liquidity
- Stop Loss and Profit Taking Orders: OracleIntegration.sol Oracle-based (starting with chainlink) pricing calculator for advanced order strategies
- Treasury Management: RebalancerInteraction.sol enables makers and takers to immediately balance their funds to a treasury (and moving forward more advanced asset management strategies).
- Resource Management: CompactInteraction.sol integrates the 1inch Limit Order Protocol with The Compact for ERC-6909 support and moving forward integration with additional cross chain intent standards such as ERC-7683 leveraging Mandates and Solver Payloads and Advanced Resource Locking.
Enhanced Swap Execution
We integrate with Tycho's indexing, simulation and execution via a TcyhoSwapExecutor which allows Solvers to provide a payload with complex routing solutions across multiple liquidity protocols. The design for United Defi allows the taker to submit a Payload with Call Data which will be executed as part of the TakerInteraction flow. This allows, if permitted by the maker, the solver to use the takers tokens and execute the trade without providing any upfront capital.
Stop Loss and Profit Taking Orders
The OracleCalculator extension is a powerful addition to the 1inch Limit Order Protocol that enables dynamic pricing based on Chainlink oracle data. This extension allows orders to be filled at prices that are calculated on-chain using real-time oracle feeds, making it possible to create orders that automatically adjust to market conditions.
Treasury Management
Implemented as an IPostInteraction the RebalancerInteraction contract allows both makers and takers to instantly move their funds to their Treasury of choice.
Resource Management
We Implemented integration with an ERC-6909 compliant locking mechanism enabling advanced resource management capabilities and laying the foundation to extend the 1inch Limit Order Protocol to open standards such as ERC-7683.
NEAR FUSION+ Smart Contract Development
NEAR Fusion+ is a comprehensive DeFi protocol that migrates 1inch's proven Limit Order Protocol and Cross-Chain Swap functionality to the NEAR blockchain. The system provides two primary capabilities: advanced limit order trading with partial fills and extensible features, and atomic cross-chain swaps secured by time-locked escrow contracts.
Implementation Limit Order Protocol
Core Components
- Compact: ERC-6909 enabled Chainlink calculator for price discovery
- ResourceManager: Manages resource locks for ERC-6909 integration
- TychoSwapExecutor: Executes complex swaps using Tycho Execution
- CompactInteraction: Post-interaction handler for resource allocation
- RebalancerInteraction: Treasury management and portfolio rebalancing
- OracleCalculator: Price oracle integration for advanced order strategies
Key Features
- Resource Locking: ERC-6909 compliant resource management
- Multi-DEX Execution: Cross-platform swap execution via Tycho
- Advanced Order Types: Stop-loss and take-profit orders
- Treasury Management: Automated portfolio rebalancing
- Oracle Integration: Chainlink price feeds for accurate pricing
Key Technology Enhancements
- Solidity based tests including a migration from
OrderUtils.js
to solidity based OrderUtils - Solidity
^0.8.30
compatibility provided by creating an interface ILimitOrderProtocol.sol and introducing LimitOrderProtocolManager for testing.
Architecture
Interactions
Enhanced Swap Execution
Tycho Execution Flow
Tycho Components
Actors
- Maker
- Creates orders specifying the spread price they are looking for (currently using chainlink Oracle)
- Solver Service
- Monitors 1inch Intents created
- Monitors Liquidity Positions on Chain using Tycho-indexer
- Simulates Solves for Orders (to see if profitable)
- Calls Resolver Contract to execute the Swap
- Solver Payload - encoded to call TychoResolver a modified version of Tycho Execution
- Calls Order Fill passing
- target: TychoResolver address
- interaction: SolverPayload
- Resolver Contract (modified version combining ResolverCrossChain and Tycho Dispatcher)
- Called by LimitOrderProtocol as part of Order.fill
- Executes swap using Makers Tokens
- Provides TakerToken to Relayer to pass back to Taker
- Transfers excess maker (or taker) tokens to Treasury
Implementation Approach
- TychoFillPredicate.sol (Predicate): copied from OracleCalculator.sol
- TychoFillInteraction.sol : copied from RebalancerInteraction.sol
- TychoResolver.sol: Copied from ResolverCrossChain.sol and Dispatcher.sol
- Tests copied from RebalancerInteraction.t.sol and enhanced with
- Creation of Swap (MakerTokens to TakerTokens) similar to
- Call of Fill Contract passing
- target: TychoResolver address
- interaction: SolverPayload
- Checking of Treasurer Balances after swap is executed
Flow
Interactions
Interactions are callbacks that enable the execution of arbitrary code, which is provided by the maker’s order or taker’s fill execution.
The order execution logic includes several steps that also involve interaction calls:
- Validate the order
- Call the maker's pre-interaction
- Transfer the maker's asset to the taker
- Call the taker's interaction
- Transfer the taker's asset to the maker
- Call the maker's post-interaction
- Emit the OrderFilled event
Calls are executed in the context of the limit order protocol. The target contract should implement the IPreInteraction
or IPostInteraction
interfaces for the maker's pre- and post-interactions and the ITakerInteraction
interface for the taker's interaction. These interfaces declare the single callback function for maker and taker interactions, respectively.
Here is how the maker’s pre- & post- interactions and the taker’s interaction are defined in the interfaces:
//Maker's pre-interaction
function preInteraction(
IOrderMixin.Order calldata order,
bytes32 orderHash,
address taker,
uint256 makingAmount,
uint256 takingAmount,
uint256 remainingMakingAmount,
bytes calldata extraData
) external;
//Maker's post-interaction
function postInteraction(
IOrderMixin.Order calldata order,
bytes32 orderHash,
address taker,
uint256 makingAmount,
uint256 takingAmount,
uint256 remainingMakingAmount,
bytes calldata extraData
) external;
//Taker's interaction
function takerInteraction(
IOrderMixin.Order calldata order,
bytes32 orderHash,
address taker,
uint256 makingAmount,
uint256 takingAmount,
uint256 remainingMakingAmount,
bytes calldata extraData
) external returns(uint256 offeredTakingAmount);
- Resolver Contract executes calls to Tycho Dispatcher or Router
- Three functions
- preInteraction: used in OracleCalculator (to ensure price before swap)
- takerInteraction used in SwapExecutor to Execute Swap by Taker
- postInteraction used in Rebalancer to Send Funds to Treasury
Design Questions
-
Interface Compatibility:
- How will the TychoResolver interface be defined to ensure compatibility with the LimitOrderProtocol bytecode deployment approach?
- Should we create a custom interface for TychoResolver or use the concrete type like the working project?
-
Predicate Logic:
- What predicate logic will TychoFill.sol use? Will it be similar to OracleCalculator.sol with price comparisons?
- How will the predicate determine when a solve is profitable vs. when it should execute?
-
Solver Payload Structure:
- What data structure will the SolverPayload contain? Will it include target addresses, amounts, and execution parameters?
- How will the payload be encoded/decoded between the Solver Service and TychoResolver?
-
Treasury Integration:
- How will excess tokens be calculated and transferred to Treasury?
- What mechanism will prevent MEV attacks on the treasury transfers?
-
Error Handling:
- How will failed solves be handled? Will orders be cancelled or retried?
- What happens if the TychoResolver execution fails during the order fill?
-
Gas Optimization:
- How will the solver service optimize gas costs across multiple orders?
- Will batch processing be implemented for multiple orders?
-
Oracle Integration:
- Will TychoFill use the same Chainlink oracle approach as OracleCalculator ?
- How will price feeds be validated and updated?
-
Cross-Chain Considerations:
- How will the ResolverCrossChain functionality be integrated with Tycho Dispatcher?
- What bridge mechanisms will be used for cross-chain swaps?
Implementation Plan
-
Phase 1: Core Contract Development
-
Create
TychoFill.sol
based onOracleCalculator.sol
- Implement predicate logic for profitable solve detection
- Add Tycho-specific price calculation methods
- Ensure interface compatibility with LimitOrderProtocol
-
Create
TychoFillInteraction.sol
based onRebalancerInteraction.sol
- Implement post-interaction logic for treasury transfers
- Add balance validation and excess token calculation
- Integrate with TychoResolver for swap execution
-
-
Phase 2: Resolver Contract Development
- Create
TychoResolver.sol
combining ResolverCrossChain and Dispatcher functionality- Implement swap execution using maker tokens
- Add taker token provision for relayer
- Integrate treasury transfer logic
- Ensure proper error handling and revert conditions
- Create
-
Phase 3: Testing Framework
- Create comprehensive test suite based on
RebalancerInteraction.t.sol
- Test order creation with Tycho-specific predicates
- Test solver payload encoding/decoding
- Test treasury balance validation
- Test cross-chain swap scenarios
- Test error conditions and edge cases
- Create comprehensive test suite based on
-
Phase 4: Integration Testing
- Test end-to-end flow from order creation to execution
- Validate predicate execution with bytecode deployment
- Test solver service integration with Tycho-indexer
- Verify treasury transfers and balance calculations
-
Phase 5: Optimization and Security
- Implement gas optimization strategies
- Add comprehensive error handling
- Implement MEV protection mechanisms
- Add monitoring and logging capabilities
-
Phase 6: Deployment and Monitoring
- Deploy contracts with proper bytecode generation
- Set up monitoring for solver service
- Implement alerting for failed solves
- Add analytics for treasury performance
Stop Loss and Profit Taking Orders
Oracle Example Order
Oracle Order Integration
Overview
The OracleCalculator extension is a powerful addition to the 1inch Limit Order Protocol that enables dynamic pricing based on Chainlink oracle data. This extension allows orders to be filled at prices that are calculated on-chain using real-time oracle feeds, making it possible to create orders that automatically adjust to market conditions.
1. What the OracleCalculator Extension Does
The OracleCalculator extension serves as an IAmountGetter
implementation that:
- Calculates dynamic exchange rates using Chainlink oracle data
- Supports both single and double oracle pricing for different token pairs
- Applies configurable spreads to provide maker/taker incentives
- Handles inverse pricing for tokens quoted in different base currencies
- Validates oracle freshness to ensure price data is current (within 4 hours)
- Integrates with predicates for conditional order execution
Key Features:
- Single Oracle Pricing: Uses one oracle to price a token relative to ETH or USD
- Double Oracle Pricing: Uses two oracles to price custom token pairs (e.g., INCH/DAI)
- Spread Application: Applies maker and taker spreads to create profitable order books
- Inverse Flag Support: Handles cases where oracle prices need to be inverted
- Oracle Freshness Check: Ensures oracle data is not stale (within 4 hours TTL)
2. Types of Orders That Can Be Created
A. Single Oracle Orders
Orders that use one Chainlink oracle to price a token relative to ETH or USD:
- ETH → DAI: Using DAI/ETH oracle
- DAI → ETH: Using DAI/ETH oracle with inverse flag
- WETH → USDC: Using USDC/ETH oracle
- USDC → WETH: Using USDC/ETH oracle with inverse flag
B. Double Oracle Orders
Orders that use two oracles to price custom token pairs:
- INCH → DAI: Using INCH/ETH and DAI/ETH oracles
- DAI → INCH: Using DAI/ETH and INCH/ETH oracles
- Custom Token Pairs: Any combination of tokens with available oracles
C. Conditional Orders (Predicates)
Orders that only execute under specific oracle conditions:
- Stop-Loss Orders: Execute only when price falls below threshold
- Take-Profit Orders: Execute only when price rises above threshold
- Range Orders: Execute only within specific price ranges
3. Fields Passed to the Extension and How They Are Populated
Extension Data Structure
The extension data is passed as bytes calldata extraData
to the getMakingAmount
and getTakingAmount
functions:
function getMakingAmount(
IOrderMixin.Order calldata order,
bytes calldata extension,
bytes32 orderHash,
address taker,
uint256 takingAmount,
uint256 remainingMakingAmount,
bytes calldata extraData // ← Extension data here
) external view returns (uint256)
Single Oracle Data Format
For single oracle pricing, the extraData
contains:
[1 byte flags][20 bytes oracle address][32 bytes spread]
- Bit 7 (0x80): Inverse flag - if set, invert the oracle price
- Bit 6 (0x40): Double price flag - if set, use double oracle mode
- Bits 0-5: Reserved
// DAI/ETH oracle at 0x1234... with 0.99 spread, no inverse
bytes memory data = abi.encodePacked(
bytes1(0x00), // flags: no inverse, no double price
address(daiOracle), // oracle address
uint256(990000000) // spread: 0.99 (990000000 / 1e9)
);
Double Oracle Data Format
For double oracle pricing, the extraData
contains:
[1 byte flags][20 bytes oracle1][20 bytes oracle2][32 bytes decimalsScale][32 bytes spread]
// INCH/DAI pricing using INCH/ETH and DAI/ETH oracles
bytes memory data = abi.encodePacked(
bytes1(0x40), // flags: double price mode
address(inchOracle), // oracle1: INCH/ETH
address(daiOracle), // oracle2: DAI/ETH
int256(0), // decimalsScale: no adjustment
uint256(1010000000) // spread: 1.01 (1010000000 / 1e9)
);
How Fields Are Populated
- Oracle Addresses: Retrieved from Chainlink's oracle registry or deployment
- Spreads: Calculated based on desired maker/taker incentives (typically 0.99 for maker, 1.01 for taker)
- Flags: Set based on pricing requirements (inverse needed, double oracle needed)
- Decimals Scale: Used to adjust for different oracle decimal precisions
4. Test Case Walkthrough
Test Case 1: ETH → DAI Chainlink Order
Scenario: Maker wants to sell 1 ETH for DAI at oracle price with spreads
Order Details:- Maker: makerAddr
- Taker: takerAddr
- Maker Asset: WETH (1 ether)
- Taker Asset: DAI (4000 ether)
- Oracle: DAI/ETH at 0.00025 ETH per DAI (1 ETH = 4000 DAI)
// Making amount data (maker spread: 0.99)
bytes memory makingAmountData = abi.encodePacked(
chainlinkCalcAddress, // Calculator address
bytes1(0x00), // No inverse flag
oracleAddress, // DAI oracle
uint256(990000000) // 0.99 spread
);
// Taking amount data (taker spread: 1.01)
bytes memory takingAmountData = abi.encodePacked(
chainlinkCalcAddress, // Calculator address
bytes1(0x80), // Inverse flag set
oracleAddress, // DAI oracle
uint256(1010000000) // 1.01 spread
);
- Taker calls
fillOrderArgs
with 4000 DAI - Protocol calls
getTakingAmount
with 4000 DAI - Calculator applies 1.01 spread: 4000 * 1.01 = 4040 DAI
- Protocol calls
getMakingAmount
with 4040 DAI - Calculator applies 0.99 spread: 4040 * 0.99 / 4000 = 0.99 ETH
- Order executes: taker receives 0.99 ETH, maker receives 4000 DAI
Result: Taker pays 4000 DAI, receives 0.99 ETH (effective rate: 1 ETH = 4040.4 DAI)
Test Case 2: DAI → ETH Chainlink Order
Scenario: Maker wants to sell 4000 DAI for ETH at oracle price
Order Details:- Maker: makerAddr
- Taker: takerAddr
- Maker Asset: DAI (4000 ether)
- Taker Asset: WETH (1 ether)
- Oracle: DAI/ETH at 0.00025 ETH per DAI
// Making amount data (inverse + maker spread)
bytes memory makingAmountData = abi.encodePacked(
chainlinkCalcAddress,
bytes1(0x80), // Inverse flag
oracleAddress,
uint256(990000000) // 0.99 spread
);
// Taking amount data (no inverse + taker spread)
bytes memory takingAmountData = abi.encodePacked(
chainlinkCalcAddress,
bytes1(0x00), // No inverse flag
oracleAddress,
uint256(1010000000) // 1.01 spread
);
- Taker calls with
makingAmount
flag set to true - Protocol calls
getMakingAmount
with 4000 DAI - Calculator applies inverse + 0.99 spread: 4000 * 0.99 / 4000 = 0.99 ETH
- Protocol calls
getTakingAmount
with 0.99 ETH - Calculator applies 1.01 spread: 0.99 * 1.01 = 1.01 ETH
- Order executes: taker receives 4000 DAI, maker receives 1.01 ETH
Result: Taker pays 1.01 ETH, receives 4000 DAI (effective rate: 1 ETH = 3960.4 DAI)
Test Case 3: INCH → DAI Double Oracle Order
Scenario: Maker wants to sell 100 INCH for DAI using double oracle pricing
Order Details:- Maker: makerAddr
- Taker: takerAddr
- Maker Asset: INCH (100 ether)
- Taker Asset: DAI (632 ether)
- Oracles: INCH/ETH (0.0001577615249227853 ETH) and DAI/ETH (0.00025 ETH)
// Making amount data (double oracle + maker spread)
bytes memory makingAmountData = abi.encodePacked(
chainlinkCalcAddress,
bytes1(0x40), // Double price flag
address(daiOracle), // Oracle1: DAI/ETH
address(inchOracle), // Oracle2: INCH/ETH
int256(0), // No decimals adjustment
uint256(990000000) // 0.99 spread
);
// Taking amount data (double oracle + taker spread)
bytes memory takingAmountData = abi.encodePacked(
chainlinkCalcAddress,
bytes1(0x40), // Double price flag
address(inchOracle), // Oracle1: INCH/ETH
address(daiOracle), // Oracle2: DAI/ETH
int256(0), // No decimals adjustment
uint256(1010000000) // 1.01 spread
);
- Taker calls with
makingAmount
flag set to true - Protocol calls
getMakingAmount
with 100 INCH - Calculator applies double oracle calculation:
- INCH price in ETH: 0.0001577615249227853
- DAI price in ETH: 0.00025
- INCH/DAI rate: 0.0001577615249227853 / 0.00025 = 0.631046
- With 0.99 spread: 100 _ 0.631046 _ 0.99 = 62.47 DAI
- Protocol calls
getTakingAmount
with 62.47 DAI - Calculator applies inverse calculation with 1.01 spread
- Order executes with calculated amounts
Result: Complex pricing based on two oracle feeds with spread adjustments
Test Case 4: Stop-Loss Order with Predicate
Scenario: Maker wants to sell INCH for DAI only if INCH/DAI price falls below 6.32
Order Details:- Maker: makerAddr
- Taker: takerAddr
- Maker Asset: INCH (100 ether)
- Taker Asset: DAI (631 ether)
- Predicate: INCH/DAI price < 6.32
// Build price call for predicate
bytes memory priceCall = abi.encodeWithSelector(
OracleCalculator .doublePrice.selector,
inchOracle, // INCH/ETH oracle
daiOracle, // DAI/ETH oracle
int256(0), // No decimals adjustment
1 ether // Base amount
);
// Build predicate call
bytes memory predicate = abi.encodeWithSelector(
swap.lt.selector, // Less than comparison
6.32 ether, // Threshold: 6.32
abi.encodeWithSelector(
swap.arbitraryStaticCall.selector,
address(oracleCalculator ),
priceCall
)
);
- Order fill is attempted
- Protocol evaluates predicate before execution
- Predicate calls
OracleCalculator .doublePrice()
with oracle data - Calculated INCH/DAI price is compared to 6.32 threshold
- If price < 6.32: order executes normally
- If price ≥ 6.32: order reverts with predicate failure
Result: Order only executes when INCH/DAI price is below the specified threshold
Test Case 5: Simple Order Without Extension
Scenario: Basic order without any Chainlink integration
Order Details:- Maker: makerAddr
- Taker: takerAddr
- Maker Asset: WETH (1 ether)
- Taker Asset: DAI (4000 ether)
- No extensions or predicates
- Taker calls
fillOrderArgs
with 4000 DAI - No extension data provided
- Protocol uses default proportional calculation
- Order executes at fixed 1:4000 ratio
Result: Simple fixed-rate order execution without dynamic pricing
Key Implementation Details
Oracle Freshness Check
if (updatedAt + _ORACLE_TTL < block.timestamp) revert StaleOraclePrice();
- Ensures oracle data is not older than 4 hours
- Prevents execution with stale price data
Spread Application
return spread * amount * latestAnswer.toUint256() / (10 ** oracle.decimals()) / _SPREAD_DENOMINATOR;
- Spreads are applied as multipliers (e.g., 990000000 = 0.99)
_SPREAD_DENOMINATOR = 1e9
for 9-decimal precision
Double Oracle Calculation
result = amount * latestAnswer1.toUint256();
if (decimalsScale > 0) {
result *= 10 ** decimalsScale.toUint256();
} else if (decimalsScale < 0) {
result /= 10 ** (-decimalsScale).toUint256();
}
result /= latestAnswer2.toUint256();
- Calculates cross-oracle pricing for custom token pairs
- Handles decimal precision adjustments between oracles
This extension enables sophisticated DeFi applications that can automatically adjust to market conditions while providing liquidity providers with profitable spreads.
Treasury Management
Treasury Management Flow
Rebalancer Requirements
- Create an Interaction Contract called RebalancerInteraction.sol (in the src directory)
- Create a test contract called RebalancerInteraction.t.sol (in the test directory)
- In RebalancerInteraction.t.sol
- Create test scenarios the same as in OracleCalculator .t.sol
- Add to that an Interaction using RebalancerInteraction.sol which
- Takes the output tokens the taker receives
- Transfers them to a third wallet (addr3) which is a treasurer
- If the transfer fails reject the order.
Rebalancer Implementation
The Rebalancer implementation has been successfully completed with the following components:
1. RebalancerInteraction.sol (src directory)
Purpose: Post-interaction contract that transfers output tokens to a treasurer wallet after successful order execution.
Key Features:
- Implements
IPostInteraction
interface for Limit Order Protocol integration - Transfers the taker's received tokens (maker asset) to a designated treasurer address
- Uses
SafeERC20
for secure token transfers with proper error handling - Reverts the entire order if transfer fails, ensuring atomic execution
- Emits
TokensTransferredToTreasurer
events for successful transfers - Validates treasurer address in constructor to prevent zero address usage
Core Functionality:
function postInteraction(
IOrderMixin.Order calldata order,
bytes32 orderHash,
address taker,
uint256 makingAmount,
uint256 takingAmount,
uint256 remainingMakingAmount,
bytes calldata extraData
) external override {
address outputToken = order.makerAsset;
uint256 outputAmount = makingAmount;
try IERC20(outputToken).safeTransferFrom(taker, treasurer, outputAmount) {
emit TokensTransferredToTreasurer(outputToken, taker, treasurer, outputAmount);
} catch {
revert TransferFailed();
}
}
2. RebalancerInteraction.t.sol (test directory)
Purpose: Comprehensive test suite that replicates all OracleCalculator scenarios with added treasurer functionality.
Test Coverage:
- Single Oracle Orders: ETH→DAI, DAI→ETH with treasurer receiving output tokens
- Double Oracle Orders: INCH→DAI with complex pricing and treasurer transfer
- Conditional Orders: Stop-loss orders with predicate validation and treasurer transfer
- Simple Orders: Basic orders without Chainlink but with treasurer transfer
- Failure Scenarios: Tests unauthorized transfers that should revert
Test Scenarios Implemented:
test_eth_to_dai_chainlink_order_with_rebalancer()
- Single oracle ETH→DAItest_dai_to_eth_chainlink_order_with_rebalancer()
- Single oracle DAI→ETH with inversetest_dai_to_1inch_chainlink_order_takingAmountData_with_rebalancer()
- Double oracle INCH→DAItest_dai_to_1inch_chainlink_order_makingAmountData_with_rebalancer()
- Double oracle with making amounttest_dai_to_1inch_stop_loss_order_with_rebalancer()
- Conditional order with predicatetest_dai_to_1inch_stop_loss_order_predicate_invalid_with_rebalancer()
- Invalid predicate testtest_eth_to_dai_stop_loss_order_with_rebalancer()
- ETH→DAI with stop-losstest_simple_order_without_extension_with_rebalancer()
- Basic order with treasurertest_simple_order_with_different_amounts_with_rebalancer()
- Partial amountstest_rebalancer_transfer_failure()
- Failure scenario testing
3. Key Implementation Details
Post-Interaction Integration
- Each test includes
buildPostInteractionCalldata(address(rebalancerInteraction))
- Post-interaction data is added to order extensions via
PostInteractionData
- Treasurer (addr3) receives the output tokens after successful order execution
Transfer Logic
- Takes output tokens: The tokens the taker receives (maker asset from the order)
- Transfers to treasurer: Moves tokens to addr3 (treasurer wallet) using
safeTransferFrom
- Rejects order on failure: If transfer fails, entire order reverts with
TransferFailed
error
Test Verification
Each test verifies:
- Order executes successfully with Chainlink pricing (where applicable)
- Treasurer receives tokens:
assertEq(token.balanceOf(addr3), expectedAmount)
- All balances are correct for maker, taker, and treasurer
- Failure scenarios revert when transfers are unauthorized
Error Handling
- TransferFailed: Reverts entire order if
safeTransferFrom
fails - InvalidTreasurer: Prevents deployment with zero address treasurer
- Predicate failures: Orders with invalid predicates revert before interaction
4. Integration with Limit Order Protocol
The implementation seamlessly integrates with the existing Limit Order Protocol:
- Extension System: Uses
PostInteractionData
extension for post-execution callbacks - Order Flow: Maintains existing order execution flow while adding treasurer transfer
- Atomic Execution: Ensures either complete success (order + transfer) or complete failure
- Event Emission: Provides transparency through
TokensTransferredToTreasurer
events
5. Security Considerations
- SafeERC20: Uses OpenZeppelin's SafeERC20 for secure token transfers
- Try-Catch: Graceful error handling prevents partial state changes
- Address Validation: Constructor validates treasurer address
- Atomic Operations: Order reverts entirely if transfer fails
- Authorization: Relies on existing token approval mechanisms
6. Use Cases
This implementation enables:
- Automated Treasury Management: Automatic transfer of trading profits to treasury
- Risk Management: Centralized control of trading outputs
- Compliance: Regulatory requirements for fund segregation
- Portfolio Rebalancing: Systematic reallocation of trading proceeds
The Rebalancer implementation successfully meets all requirements from the specification and provides a robust, secure, and comprehensive solution for automated treasury management in limit order trading.
Test Results
10 out of 10 tests passing (100% success rate)✅ All Tests Passing:
test_eth_to_dai_chainlink_order_with_rebalancer()
- Single oracle ETH→DAItest_dai_to_eth_chainlink_order_with_rebalancer()
- Single oracle DAI→ETH with inversetest_eth_to_dai_stop_loss_order_with_rebalancer()
- Stop-loss with predicatetest_simple_order_without_extension_with_rebalancer()
- Basic order without extensionstest_simple_order_with_different_amounts_with_rebalancer()
- Different order amountstest_rebalancer_transfer_failure()
- Transfer failure handlingtest_dai_to_1inch_stop_loss_order_predicate_invalid_with_rebalancer()
- Invalid predicatetest_dai_to_1inch_chainlink_order_makingAmountData_with_rebalancer()
- Double oracle with making amounttest_dai_to_1inch_chainlink_order_takingAmountData_with_rebalancer()
- Double oracle with taking amounttest_dai_to_1inch_stop_loss_order_with_rebalancer()
- Complex double oracle with stop-loss predicate
🎯 Core Functionality Verified:
- ✅ Post-interaction transfers tokens to treasurer
- ✅ Proper token approvals and transfers
- ✅ Balance verification accounting for treasurer transfers
- ✅ Error handling with transfer failures
- ✅ Atomic execution (orders either complete fully or revert entirely)
- ✅ Support for multiple token types (WETH, DAI, INCH)
- ✅ Complex oracle-based pricing scenarios
Resource Management
Resource Management Architecture
Resource Management Components
Requirements
- Read lib\the-compact\README.md (open in editor) to understand how the compact works
- We are looking to create an end to end flow where
- We register a new contract ResourceManager.sol as a ResourceManager
- We Register ChainLinkCompactInteraction.sol as the Arbiter
- The Maker (the Swapper in compact terms signs permission for their tokens (or ETH) to be stored in the-compact as ERC-6909)
- ChainLinkCompact.sol checks that the we have a ResourceLock for the amount required.
- ChainLinkCompact then executes the trade using the same logic that was in ChainLinkCalculator and creates a resource lock for their (tokens/ETH)
- ChainLinkCompactInteraction is copied from RebalancerInteraction it takes the output tokens provided by the Taker and
- If they are >= TakerAmount then it calls the ResourceManager to lock the funds
- It then does the token transfer to the treasurer the same as it was done in the original RebalancerInteraction
Design Questions
-
Resource Manager Registration: How should we register the LimitOrderProtocol as a ResourceManager in The Compact? Should it be a separate contract or integrated directly?
- Answer: We are registering it as a separate contract let's call it ResourceManager.sol and this contract will be called by ChainLinkCompact to lock the resources before calling the swap on LimitOrderProtocl
-
Arbiter Implementation: Should ChainLinkCompactInteraction.sol be a standalone arbiter or integrated with existing ChainLinkCalculator logic?
- Answer: It should be Standalone ChainLinkCalculator and RebalancerInteraction remain unchanged
-
Token Locking Strategy: Should makers lock their entire balance upfront or lock tokens dynamically when orders are matched?
- Answer: Initially Lock their whole balance
-
Resource Lock Scope: Should resource locks be chain-specific or multichain for cross-chain order execution?
- Answer: Chain-specific
-
Allocator Selection: Which allocator should we use for the resource locks? Should we create a custom allocator or use existing ones like Smallocator/Autocator?
- Answer: Create a custom Allocator based on Autocator(which is used for End User signing which is the Maker in our case)
- The logic for calling this should be in ChainLinkCompact.t.sol
- Moving forward we will also create a custom Smallocator used when smart contract call this
-
EIP-712 Signature Structure: How should we structure the EIP-712 signatures for the compact agreements? Should we include mandate data for additional conditions?
- Answer: For Phase 1 we do not need to add mandate data or Solver Payloads we will incorporate those in a later phase
-
Fallback Mechanisms: What should happen if the arbiter fails to process a claim? Should we implement emissary fallbacks?
- If an arbiter fails to process the claim the swap should revert
-
Gas Optimization: How can we optimize gas usage for the ERC-6909 integration, especially for batch operations?
- We will optimize gas in phase 2
-
Error Handling: How should we handle cases where resource locks are insufficient or expired?
- We revert the transaction with custom errors stating the reason for the failure
-
Integration Points: Should the ERC-6909 functionality be optional (opt-in) or mandatory for all orders?
- Optional set by a boolean ERC-6909 flag for now
- Later this may move to an enum with additional swap types
Implementation
Phase 1: Core Contract Development
-
Create ResourceManager.sol - New contract
- Register as ResourceManager in The Compact
- Handle resource lock creation and management for makers
- Implement allocator integration for order validation
- Called by ChainLinkCompact to lock resources before swap execution
-
Create ChainLinkCompact.sol - Copy from ChainLinkCalculator.sol
- Add ERC-6909 flag for optional functionality
- Integrate with The Compact for resource lock verification
- Add ERC-6909 token validation before order execution
- Call ResourceManager.sol to lock resources before LimitOrderProtocol execution
- Implement custom error handling for insufficient/expired locks
-
Create ChainLinkCompactInteraction.sol - Copy from RebalancerInteraction.sol
- Implement IArbiter interface for The Compact
- Add resource lock creation for taker's output tokens
- Maintain treasurer transfer functionality
- Add EIP-712 signature verification for compact agreements
- Revert entire transaction if arbiter fails to process claim
-
Create Custom Allocator - Based on Autocator
- Implement IAllocator interface
- Handle end-user (Maker) signing authorization
- Add nonce management for compact claims
- Implement claim authorization logic
- Logic for calling this should be in ChainLinkCompact.t.sol
Phase 2: Integration & Testing
-
Compact Registration System
- Implement EIP-712 signature generation for makers (no mandate data for Phase 1)
- Create compact registration functions
- Add chain-specific resource lock scope
- Implement upfront token locking strategy
-
Testing Suite
- Unit tests for each contract
- Integration tests for end-to-end flow
- Test ERC-6909 flag functionality
- Test custom error handling scenarios
Phase 3: Advanced Features
-
Gas Optimization
- Optimize gas usage for ERC-6909 integration
- Implement batch operations optimization
- Profile and optimize critical paths
-
Enhanced Features
- Add mandate data structure for order conditions
- Implement multichain support
- Create custom Smallocator for smart contract calls
- Add emissary fallback mechanisms
- Implement enum for additional swap types beyond boolean flag
Technical Architecture
Core Flow:- Maker deposits tokens into The Compact (creates ERC-6909 resource lock)
- Maker signs EIP-712 compact agreement with arbiter (ChainLinkCompactInteraction)
- Order is posted to LimitOrderProtocol with ERC-6909 extension
- Taker fills order through ChainLinkCompact.sol
- ChainLinkCompactInteraction processes claim:
- Verifies resource lock availability
- Executes trade using ChainLinkCalculator logic
- Creates new resource lock for taker's output tokens
- Transfers tokens to treasurer
- Calls ResourceManager to lock funds
ITheCompact
- For resource lock managementIAllocator
- For claim authorizationIArbiter
- For claim processingIEmissary
- For fallback verification
Compact
- EIP-712 payload for single resource lockBatchCompact
- EIP-712 payload for multiple resource locksMandate
- Witness data for order conditionsClaim
- Claim payload for processing
Future Test Enhancements
For ERC-6909 integration, additional test categories will be needed:
-
ERC-6909 Resource Lock Tests
- Resource lock creation and validation
- Insufficient lock handling
- Lock expiration scenarios
-
Compact Integration Tests
- EIP-712 signature verification
- Compact agreement validation
- Arbiter claim processing
-
Resource Manager Tests
- Lock management functionality
- Allocator integration
- Error handling for resource conflicts
-
End-to-End Flow Tests
- Complete maker-to-taker flow
- Treasurer integration
- Cross-contract interaction validation
NEAR FUSION+ Smart Contract Development
NEAR Smart Contract Architecture
NEAR Limit Order Protocol Contracts
NEAR Escrow Smart Contracts
Overview
NEAR Fusion+ is a comprehensive DeFi protocol that migrates 1inch's Limit Order Protocol and Cross-Chain Swap functionality to the NEAR blockchain. This project implements advanced trading features including limit orders, cross-chain atomic swaps, and sophisticated escrow mechanisms.
Architecture
The protocol consists of several interconnected smart contracts that work together to provide a complete DeFi trading experience:
Core Components
- Limit Order Protocol - Handles limit order creation, execution, and management
- Cross-Chain Swap - Enables atomic swaps across different blockchains
- Escrow System - Manages secure fund escrow for cross-chain operations
- Fee Management - Handles fee collection and distribution
- Merkle Validation - Provides proof validation for complex order structures
Contract Structure
src/
├── limit-order-protocol/ # Main limit order functionality
├── cross-chain-swap/ # Cross-chain atomic swap implementation
├── base-escrow-factory/ # Advanced escrow factory with Merkle validation
├── escrow-factory/ # Standard escrow factory
├── escrow-src/ # Source chain escrow contract
├── escrow-dst/ # Destination chain escrow contract
├── fee-taker/ # Fee collection and management
└── merkle-storage-invalidator/ # Merkle proof validation
Key Features
- Limit Orders: Advanced limit order protocol with partial fills and multiple execution strategies
- Cross-Chain Swaps: Atomic swaps between different blockchains with time-locked escrows
- Merkle Proofs: Efficient validation for complex order structures
- Fee Management: Flexible fee collection and distribution mechanisms
- Security: Comprehensive validation and timelock mechanisms
Documentation Sections
- Architecture Overview
- Contract Documentation
- Integration Guide
- Security Considerations
- API Reference
- Deployment Guide
Quick Start
- Build Contracts:
cargo near build
- Run Tests:
cargo test
- Deploy: Use the deployment scripts in
deployment-scripts/
Development
- Rust Version: See
rust-toolchain.toml
- NEAR SDK: v5.15.1
- Testing: Integration tests in
integration-tests/
Contributing
Please refer to the main README.md for development setup and contribution guidelines.