This project is a Proof of Concept (PoC) demonstrating how t1 can verify transactions on Sepolia and trigger payments based on intent fulfillment.
Here's what an Intent looks like for this example:
struct Intent {
address creator; // The user who created the intent.
address recipient; // The recipient on the destination chain.
uint256 amount; // Amount expected to be received.
uint256 fee; // Fee offered to the filler.
address filler; // The address fulfilling the intent.
uint256 deposit; // Deposit made by the filler.
uint256 claimTimestamp; // Timestamp when the intent was claimed.
bool fulfilled; // Whether the intent has been fulfilled.
}The project currently allows an Intent Creator to declare an amount of tokens that they would like sent to a recipient address. For the purposes of this PoC, it is assumed that the creator wants Ether sent on Sepolia.
By default, the Filler's reward is at least 1% of the amount set by the Intent Creator, but an additional fee can be included to further incentivize Fillers.
To prevent multiple Fillers from competing to fulfill the same Intent—potentially resulting in duplicate payments to the recipient—the contract enforces a claim mechanism. Only the first Filler to successfully claim an Intent secures the right to fulfill it and receive the reward.
To prevent Fillers from exploiting the system by claiming an Intent without fulfilling it, they are required to place a deposit when claiming. If the Filler successfully completes the Intent within the claimTimeout window, they can reclaim their deposit along with any addition fee the Intent Creator set.
However, if the Intent remains unfulfilled beyond the claimTimeout, the Intent Creator has the right to close the Intent and retain the Filler’s deposit as compensation.
-
Intent Creation
- A user (creator) calls
createIntenton t1, specifying therecipient,amount, andfee. - The contract emits an
IntentCreatedevent.
- A user (creator) calls
-
Intent Claiming
- A filler calls
claimIntentand provides a deposit. - The contract records the filler’s address and timestamp.
- The contract emits an
IntentClaimedevent.
- A filler calls
-
Intent Fulfillment
- The filler transfers the expected amount to the recipient on Sepolia.
- The
MockSepoliaPaymentcontract emits anIntentFulfilledevent. - The relayer detects this event and submits proof to
t1.
-
Verification & Payment
- The contract verifies the fulfillment via
verifyFill. - The filler can call
claimPaymentto receive their reward. - The contract emits a
FillerPaidevent.
- The contract verifies the fulfillment via
-
Expiration & Refunds
- If an intent is not fulfilled within the
claimTimeoutwindow, the creator can callcloseExpiredIntent. - The contract refunds the creator and emits an
IntentClosedevent. - If the intent expires, the creator can reclaim their funds along with the Filler’s deposit as compensation.
- If an intent is not fulfilled within the
-
Contract Shutdown
- The owner can call
withdrawAndDisableto remove all funds held by the contract.
- The owner can call
npm installCreate a .env file and configure:
SEPOLIA_WSS_URL=wss://...
SEPOLIA_URL=https://
T1_URL=https://...
WALLET_PRIVATE_KEY=your_private_key
INTENT_CREATOR=0xYourAddress // Public key associated with the private key above
// Intent configurations can be changed as needed
INTENT_AMOUNT=0.001 //amount of ETH requested to be send to recipient
INTENT_FEE=0.001 //additional fee paid to Filler as incentive
FILLER_DEPOSIT=0.005 //min deposit requierd to claim an Intent
INTENT_ID=0 //adjust to interact with the correct Intent with scripts
EXPIRE_TIME=1 //time in secondsnpm run deployContractsDeploys the IntentVerification and MockSepoliaPayment contracts and starts the relayer in a new terminal.
Note: Be sure to adjust the INTENT_ID in the .env when running this script multiple times on the same test contract.
This command executes the full process resulting in a sucessfull Intent fulfillment and payment claim:
npm run intentClaimFlowThis automatically runs the following commands sequentially:
npm run createIntent- Creates an intent on t1.npm run queryIntent- Queries the created intent.npm run claimIntent- A filler claims the intent.npm run queryIntent- Queries the created intent.npm run fulfillIntent- The filler transfers funds on Sepolia.npm run queryIntent- Queries the intent again to verify fulfillment.npm run claimPayment- The filler claims their reward.
Note: Be sure to adjust the INTENT_ID in the .env when running this script multiple times on the same test contract.
Simulates the full Intent lifecyle in the case that an Intent was claimed by a Filler but not completed in time
npm run intentExpireFlowThis automatically runs the following commands sequentially:
npm run createIntent- Creates an intent on t1.npm run queryIntent- Queries the created intent.npm run claimIntent- A filler claims the intent.npm run queryIntent- Queries the intent.npm run closeExpiredIntent- Waits for expiration and closes the intent.
Note: Be sure to adjust the INTENT_ID in the .env when running this script multiple times on the same test contract.
This command deploys contracts, starts the relayer and runs the full intent claim flow:
npm run testClaimPathThis automatically runs the following commands sequentially:
npm run deployContracts- Deploy Contracts & Start Relayer (see above)npm run intentClaimFlow- Run the Full Intent Claim Flow (see above)
Note: Be sure to adjust the INTENT_ID in the .env when running this script multiple times on the same test contract.
This command deploys contracts, starts the relayer and runs the expiration flow:
npm run testExpirePathThis automatically runs the following commands sequentially:
npm run deployContracts- Deploy Contracts & Start Relayer (see above)npm run intentExpireFlow- Run the Full Intent Claim Flow (see above)
startRelayer: Runs the relayer script.startRelayerDetached: Starts the relayer in a new terminal.deployContracts: Deploys all contracts and starts the relayer.deployIntentVerification: DeploysIntentVerificationcontract.deployMockSepolia: DeploysMockSepoliaPaymentcontract.createIntent: Creates an intent on t1.claimIntent: Claims an intent by a filler.fulfillIntent: Fulfills an intent on Sepolia.queryIntent: Fetches details of an intent.claimPayment: Claims the filler’s payment once verified.closeExpiredIntent: Closes an expired intent and refunds.withdrawAndDisable: Withdraws funds and disables the contract.
Run full suite of Hardhat Tests:
npx hardhat test- Remove fulfilled or expired intents to free storage.
- Use event-based tracking (The Graph) instead of on-chain queries.
- Implement pagination for fetching multiple intents efficiently.
- Avoid looping through large datasets to prevent high gas costs.
- Move Intent data off-chain where possible.
- Cap the number of active intents per user to prevent overuse.
- Enforce a small mandatory Filler fee to prevent spam.
- Batch-close expired intents in a single transaction.
- Use Chainlink Keepers or bots to automatically close expired intents.
- Use cross-chain messaging instead of a centralized relayer.