Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions contracts/wrappers/AcrossIntentWrapper.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
pragma solidity ^0.8.27;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface AcrossV3SpokePool {
function depositV3(
address depositor,
address recipient,
address inputToken,
address outputToken,
uint256 inputAmount,
uint256 outputAmount,
uint256 destinationChainId,
address exclusiveRelayer,
uint32 quoteTimestamp,
uint32 fillDeadline,
uint32 exclusivityDeadline,
bytes calldata message
) external payable;
}

contract AcrossIntentWrapper {
error InputAmountMismatch(uint256 balance, uint256 inputAmount);

function depositV3Composable (
address pool, // pool to call
address depositor,
address recipient,
address inputToken,
address outputToken,
uint256 inputAmount,
uint256 outputRatioPacked, // MS 128bytes: output ratio = (quotedInputAmount * OUTPUT_RATIO_PRECISION) / quotedOutputAmount ; LS 128bytes: OUTPUT_RATIO_PRECISION
uint256 destinationChainId,
address exclusiveRelayer,
uint32 quoteTimestamp,
uint32 fillDeadline,
uint32 exclusivityDeadline,
bytes calldata message
) external payable {
// 1. Approve input amount to the pool
uint256 balance = IERC20(inputToken).balanceOf(address(this));
require (balance == inputAmount, InputAmountMismatch(balance, inputAmount));
IERC20(inputToken).approve(pool, inputAmount);

// 2. Unpack the output ratio
uint256 outputRatio = outputRatioPacked >> 128;
uint256 outputRatioPrecision = outputRatioPacked & 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff;

// 3. Get the output amount
uint256 outputAmount = inputAmount * outputRatio / outputRatioPrecision;

// 4. Call the pool with the runtime amount
AcrossV3SpokePool(pool).depositV3{value: msg.value}(
depositor,
recipient,
inputToken,
outputToken,
inputAmount,
outputAmount,
destinationChainId,
exclusiveRelayer,
quoteTimestamp,
fillDeadline,
exclusivityDeadline,
message
);
}
}
5 changes: 5 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,10 @@
tab_width = 4
wrap_comments = true

[rpc_endpoints]
optimism = "${OPTIMISM_MAINNET_RPC_URL}"
optimism-sepolia = "${OPTIMISM_SEPOLIA_RPC_URL}"
base = "${BASE_RPC_URL}"
base-sepolia = "${BASE_SEPOLIA_RPC_URL}"

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
23 changes: 23 additions & 0 deletions scripts/foundry-deploy/DeployAcrossIntentWrapper.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

import {AcrossIntentWrapper} from "../../contracts/wrappers/AcrossIntentWrapper.sol";
import {Script} from "forge-std/Script.sol";
import {console2} from "forge-std/console2.sol";

contract DeployAcrossIntentWrapper is Script {

function setUp() public {

}

function run() public {
vm.startBroadcast();

AcrossIntentWrapper acrossIntentWrapper = new AcrossIntentWrapper();

vm.stopBroadcast();
}
}

// OP mainnet: 0xB9F82b52Afde09D0E2CC0748a66D1Df76C18A1c7 (with emit)