Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
8f5b5fe
chore: boilerplate
rymcol Oct 2, 2025
f357f5d
fix: nonce issues in burst resolved
rymcol Oct 3, 2025
20a25da
fix: nonce issues in sustained test
rymcol Oct 3, 2025
141dc53
fix: forge fmt
rymcol Oct 3, 2025
77ddf94
fix: prettier formatting for docs
rymcol Oct 3, 2025
239f709
fix: minor text change for clarity
rymcol Oct 3, 2025
2dbdee0
fix: address comments on logs
rymcol Oct 8, 2025
491479a
Merge branch 'canary' of github.com:t1protocol/t1 into xCR/bridge-loa…
rymcol Oct 22, 2025
5d1d748
fix: pr comments, stop batching
rymcol Oct 23, 2025
d524ef2
fix: limits
rymcol Oct 23, 2025
127ece7
fix: load test subfoldering
rymcol Oct 23, 2025
36dd42e
fix: extra ;
rymcol Oct 23, 2025
8c3b7f5
fix: syntax
rymcol Oct 23, 2025
7da2862
Revert "fix: load test subfoldering"
rymcol Oct 24, 2025
bbac22a
feat: bash load test
rymcol Oct 24, 2025
3aabd85
fix: working bash -> solidity
rymcol Oct 27, 2025
6b811cc
feat: random direction
rymcol Oct 27, 2025
55b1d95
feat: multi-asset load testing
rymcol Oct 27, 2025
2809a18
Merge branch 'canary' into bash-load
rymcol Nov 13, 2025
50c6b83
Merge branch 'canary' of github.com:t1protocol/t1 into bash-load
rymcol Nov 14, 2025
de75f86
Merge branch 'bash-load' of github.com:t1protocol/t1 into bash-load
rymcol Nov 14, 2025
b9a37e0
fix: linting
rymcol Nov 14, 2025
2fe0372
fix: prettier write
rymcol Nov 14, 2025
9ad63c6
Revert "fix: prettier write"
rymcol Nov 18, 2025
eb8ffd0
chore: forge fmt
kss-t1 Dec 29, 2025
d0e9e9b
Merge remote-tracking branch 'origin/canary' into bash-load
kss-t1 Dec 29, 2025
9ca5ad1
chore: forge fmt
kss-t1 Dec 29, 2025
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
10 changes: 5 additions & 5 deletions contracts/script/test/7683/T1ERC7683ArbToBase.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ import { OnchainCrossChainOrder } from "../../../src/interfaces/IERC7683.sol";
import { T1ERC7683 } from "../../../src/7683/T1ERC7683.sol";
import { T1Constants } from "../../../src/libraries/constants/T1Constants.sol";

uint32 constant ORIGIN_CHAIN = uint32(T1Constants.ARBITRUM_SEPOLIA_CHAIN_ID);
uint32 constant DESTINATION_CHAIN = uint32(T1Constants.BASE_SEPOLIA_CHAIN_ID);
uint32 constant ORIGIN_CHAIN = uint32(T1Constants.ARBITRUM_MAINNET_CHAIN_ID);
uint32 constant DESTINATION_CHAIN = uint32(T1Constants.BASE_MAINNET_CHAIN_ID);
uint32 constant AMOUNT_IN = 100;

// Step 1: Setup Alice's account, sign and relay intent
contract AliceSetupScript is Script {
T1ERC7683 public l1_7683;

function run() external {
vm.createSelectFork(vm.rpcUrl("arbitrum_sepolia"));
vm.createSelectFork(vm.rpcUrl("arbitrum"));
l1_7683 = T1ERC7683(vm.envAddress("ARB_T1_PULL_BASED_7683_PROXY_ADDR"));
// Load Alice's private key from env
uint256 alicePk = vm.envUint("ALICE_PRIVATE_KEY");
Expand All @@ -29,8 +29,8 @@ contract AliceSetupScript is Script {
vm.startBroadcast(alicePk);

// Approve tokens
ERC20 inputToken = ERC20(vm.envAddress("ARBITRUM_SEPOLIA_USDT_ADDR"));
ERC20 outputToken = ERC20(vm.envAddress("BASE_SEPOLIA_USDT_ADDR"));
ERC20 inputToken = ERC20(vm.envAddress("USDC_ARB"));
ERC20 outputToken = ERC20(vm.envAddress("USDC_BASE"));
inputToken.approve(address(l1_7683), type(uint256).max);

// Prepare order data
Expand Down
10 changes: 5 additions & 5 deletions contracts/script/test/7683/T1ERC7683BaseToArb.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ import { OnchainCrossChainOrder } from "../../../src/interfaces/IERC7683.sol";
import { T1ERC7683 } from "../../../src/7683/T1ERC7683.sol";
import { T1Constants } from "../../../src/libraries/constants/T1Constants.sol";

uint32 constant ORIGIN_CHAIN = uint32(T1Constants.BASE_SEPOLIA_CHAIN_ID);
uint32 constant DESTINATION_CHAIN = uint32(T1Constants.ARBITRUM_SEPOLIA_CHAIN_ID);
uint32 constant ORIGIN_CHAIN = uint32(T1Constants.BASE_MAINNET_CHAIN_ID);
uint32 constant DESTINATION_CHAIN = uint32(T1Constants.ARBITRUM_MAINNET_CHAIN_ID);
uint32 constant AMOUNT_IN = 100;

// Step 1: Setup Alice's account, sign and relay intent
contract AliceSetupScript is Script {
T1ERC7683 public l1_7683;

function run() external {
vm.createSelectFork(vm.rpcUrl("base_sepolia"));
vm.createSelectFork(vm.rpcUrl("base"));
l1_7683 = T1ERC7683(vm.envAddress("BASE_T1_PULL_BASED_7683_PROXY_ADDR"));
// Load Alice's private key from env
uint256 alicePk = vm.envUint("ALICE_PRIVATE_KEY");
Expand All @@ -29,8 +29,8 @@ contract AliceSetupScript is Script {
vm.startBroadcast(alicePk);

// Approve tokens
ERC20 inputToken = ERC20(vm.envAddress("BASE_SEPOLIA_USDT_ADDR"));
ERC20 outputToken = ERC20(vm.envAddress("ARBITRUM_SEPOLIA_USDT_ADDR"));
ERC20 inputToken = ERC20(vm.envAddress("USDC_BASE"));
ERC20 outputToken = ERC20(vm.envAddress("USDC_ARB"));
inputToken.approve(address(l1_7683), type(uint256).max);

// Prepare order data
Expand Down
131 changes: 131 additions & 0 deletions contracts/script/test/7683/loadtesting/loadtest.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import { Script } from "forge-std/Script.sol";
import { console2 } from "forge-std/console2.sol";
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { TypeCasts } from "@hyperlane-xyz/libs/TypeCasts.sol";
import { OrderData, OrderEncoder } from "../../../../src/libraries/7683/OrderEncoder.sol";
import { OnchainCrossChainOrder } from "../../../../src/interfaces/IERC7683.sol";
import { T1ERC7683 } from "../../../../src/7683/T1ERC7683.sol";
import { T1Constants } from "../../../../src/libraries/constants/T1Constants.sol";

contract LoadTest is Script {
T1ERC7683 public l1_7683;

function run(string memory direction, string memory tokenPair) external {
// Define chain IDs
uint32 arbitrumChainId = uint32(T1Constants.ARBITRUM_MAINNET_CHAIN_ID);
uint32 baseChainId = uint32(T1Constants.BASE_MAINNET_CHAIN_ID);

// Declare variables to be set based on direction and token pair
uint32 originChain;
uint32 destinationChain;
string memory forkUrl;
address t1ProxyAddr;
address inputTokenAddr;
address outputTokenAddr;
address destinationSettlerAddr;

// Set chain and proxy addresses based on direction
if (keccak256(abi.encodePacked(direction)) == keccak256(abi.encodePacked("arb-to-base"))) {
originChain = arbitrumChainId;
destinationChain = baseChainId;
forkUrl = "arbitrum";
t1ProxyAddr = vm.envAddress("ARB_T1_PULL_BASED_7683_PROXY_ADDR");
destinationSettlerAddr = vm.envAddress("BASE_T1_PULL_BASED_7683_PROXY_ADDR");
} else if (keccak256(abi.encodePacked(direction)) == keccak256(abi.encodePacked("base-to-arb"))) {
originChain = baseChainId;
destinationChain = arbitrumChainId;
forkUrl = "base";
t1ProxyAddr = vm.envAddress("BASE_T1_PULL_BASED_7683_PROXY_ADDR");
destinationSettlerAddr = vm.envAddress("ARB_T1_PULL_BASED_7683_PROXY_ADDR");
} else {
revert("Invalid direction: use 'arb-to-base' or 'base-to-arb'");
}

// Set token addresses based on token pair
if (keccak256(abi.encodePacked(tokenPair)) == keccak256(abi.encodePacked("usdc-usdc"))) {
inputTokenAddr = originChain == arbitrumChainId ? vm.envAddress("USDC_ARB") : vm.envAddress("USDC_BASE");
outputTokenAddr =
destinationChain == arbitrumChainId ? vm.envAddress("USDC_ARB") : vm.envAddress("USDC_BASE");
} else if (keccak256(abi.encodePacked(tokenPair)) == keccak256(abi.encodePacked("weth-weth"))) {
inputTokenAddr = originChain == arbitrumChainId ? vm.envAddress("WETH_ARB") : vm.envAddress("WETH_BASE");
outputTokenAddr =
destinationChain == arbitrumChainId ? vm.envAddress("WETH_ARB") : vm.envAddress("WETH_BASE");
} else if (keccak256(abi.encodePacked(tokenPair)) == keccak256(abi.encodePacked("usdc-weth"))) {
inputTokenAddr = originChain == arbitrumChainId ? vm.envAddress("USDC_ARB") : vm.envAddress("USDC_BASE");
outputTokenAddr =
destinationChain == arbitrumChainId ? vm.envAddress("WETH_ARB") : vm.envAddress("WETH_BASE");
} else if (keccak256(abi.encodePacked(tokenPair)) == keccak256(abi.encodePacked("weth-usdc"))) {
inputTokenAddr = originChain == arbitrumChainId ? vm.envAddress("WETH_ARB") : vm.envAddress("WETH_BASE");
outputTokenAddr =
destinationChain == arbitrumChainId ? vm.envAddress("USDC_ARB") : vm.envAddress("USDC_BASE");
} else {
revert("Invalid token pair: use 'usdc-usdc', 'weth-weth', 'usdc-weth', or 'weth-usdc'");
}

// Select the appropriate fork
vm.createSelectFork(vm.rpcUrl(forkUrl));
l1_7683 = T1ERC7683(t1ProxyAddr);

// Load Alice's private key from env
uint256 alicePk = vm.envUint("ALICE_PRIVATE_KEY");
address alice = vm.addr(alicePk);

// Start broadcasting as Alice
vm.startBroadcast(alicePk);

// Approve tokens
ERC20 inputToken = ERC20(inputTokenAddr);
ERC20 outputToken = ERC20(outputTokenAddr);
inputToken.approve(address(l1_7683), type(uint256).max);

// Prepare order data
OrderData memory orderData = OrderData({
sender: TypeCasts.addressToBytes32(alice),
recipient: TypeCasts.addressToBytes32(alice),
inputToken: TypeCasts.addressToBytes32(address(inputToken)),
outputToken: TypeCasts.addressToBytes32(address(outputToken)),
amountIn: 100, // AMOUNT_IN constant replaced with literal for simplicity
minAmountOut: 100 * 9 / 10, // 90% of amountIn
senderNonce: uint32(
uint256(keccak256(abi.encodePacked(block.timestamp, block.prevrandao, msg.sender))) % 10_000
), // Random number between 0 and 9999
originDomain: originChain,
destinationDomain: destinationChain,
destinationSettler: TypeCasts.addressToBytes32(destinationSettlerAddr),
fillDeadline: uint32(block.timestamp + 5 minutes),
closedAuction: true,
data: new bytes(0)
});

// Encode and open order
bytes memory encodedOrder = OrderEncoder.encode(orderData);
OnchainCrossChainOrder memory order =
_prepareOnchainOrder(encodedOrder, orderData.fillDeadline, OrderEncoder.orderDataType());
l1_7683.open(order);

// Log order details
bytes32 id = OrderEncoder.id(orderData);
console2.logString("orderId: ");
console2.logBytes32(id);
console2.logString("encodedOrder: ");
console2.logBytes(encodedOrder);

vm.stopBroadcast();
}

function _prepareOnchainOrder(
bytes memory orderData,
uint32 fillDeadline,
bytes32 orderDataType
)
internal
pure
returns (OnchainCrossChainOrder memory)
{
return
OnchainCrossChainOrder({ fillDeadline: fillDeadline, orderDataType: orderDataType, orderData: orderData });
}
}
49 changes: 49 additions & 0 deletions contracts/script/test/7683/loadtesting/loadtest.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/bin/bash

# Suppress Foundry nightly warning
export FOUNDRY_DISABLE_NIGHTLY_WARNING=1

# Source env
if [[ -f ".env" ]]; then
source .env
fi

# Number of times to run the script
RUN_COUNT=$1

# Check if RUN_COUNT is provided and is a positive integer
if [[ -z "$RUN_COUNT" || ! "$RUN_COUNT" =~ ^[0-9]+$ ]]; then
echo "Error: Please provide a valid number of runs as the first argument."
exit 1
fi

# Array of possible directions
DIRECTIONS=("arb-to-base" "base-to-arb")

# Array of possible token pairs
TOKEN_PAIRS=("usdc-usdc" "weth-weth" "usdc-weth" "weth-usdc")

# Loop to run the forge script RUN_COUNT times
for ((i=1; i<=RUN_COUNT; i++))
do
# Randomly select a direction
DIRECTION=${DIRECTIONS[$RANDOM % ${#DIRECTIONS[@]}]}

# Randomly select a token pair
TOKEN_PAIR=${TOKEN_PAIRS[$RANDOM % ${#TOKEN_PAIRS[@]}]}

# Select RPC URL based on direction
if [[ "$DIRECTION" == "arb-to-base" ]]; then
RPC_URL=$ARBITRUM_RPC
else
RPC_URL=$BASE_RPC
fi

echo "Running script $i/$RUN_COUNT in direction: $DIRECTION with token pair: $TOKEN_PAIR"

forge script ./script/test/7683/loadtesting/loadtest.s.sol:LoadTest \
--rpc-url "$RPC_URL" \
--broadcast \
--private-key "$ALICE_PRIVATE_KEY" \
--sig "run(string,string)" "$DIRECTION" "$TOKEN_PAIR"
done