Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
1 change: 1 addition & 0 deletions TESTSINVENTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ Table of tests currently implemented or being implemented in the E2E repository.
| Test Sovereign Chain Bridge Events | [Link](./tests/aggkit/bridge-sovereign-chain-e2e.bats#L75) | |
| Test block gas limit increase to 60M | [Link](./tests/fusaka/eip7935.bats#L19) | |
| Test execute multiple claimMessages via testClaim with internal reentrancy and bridgeAsset call | [Link](./tests/aggkit/claim-reetrancy.bats#L477) | |
| Test internal bridge transactions -> 2 bridge tx with different amounts | [Link](./tests/aggkit/internal-bridge-tx.bats#L62) | |
| Test new RPC endpoint eth_config | [Link](./tests/fusaka/eip7910.bats#L19) | |
| Test reentrancy protection for bridge claims - should prevent double claiming | [Link](./tests/aggkit/claim-reetrancy.bats#L69) | |
| Test triple claim internal calls -> 1 fail (same global index), 1 success (same global index) and 1 fail (different global index) | [Link](./tests/aggkit/internal-claims.bats#L1355) | |
Expand Down
347 changes: 347 additions & 0 deletions core/contracts/bridgeAsset/InternalBridgeTx.json

Large diffs are not rendered by default.

111 changes: 111 additions & 0 deletions core/contracts/bridgeAsset/InternalBridgeTx.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// SPDX-License-Identifier: AGPL-3.0

pragma solidity ^0.8.20;
import "./Interfaces.sol";

contract InternalBridgeTx {
event MessageReceived(address destinationAddress);
event BridgeTransactionExecuted(uint32 destinationNetwork, address destinationAddress, uint256 amount);
event UpdateBridgeParameters();

IPolygonZkEVMBridgeV2 public immutable bridgeAddress;

// First bridge transaction parameters
uint32 destinationNetwork1;
address destinationAddress1;
uint256 amount1;
address token1;
bool forceUpdateGlobalExitRoot1;
bytes permitData1;

// Second bridge transaction parameters
uint32 destinationNetwork2;
address destinationAddress2;
uint256 amount2;
address token2;
bool forceUpdateGlobalExitRoot2;
bytes permitData2;

bytes data;

constructor(IPolygonZkEVMBridgeV2 _bridgeAddress) {
bridgeAddress = _bridgeAddress;
}

function updateBridgeParameters(
// First bridge transaction parameters
uint32 _destinationNetwork1,
address _destinationAddress1,
uint256 _amount1,
address _token1,
bool _forceUpdateGlobalExitRoot1,
bytes calldata _permitData1,
// Second bridge transaction parameters
uint32 _destinationNetwork2,
address _destinationAddress2,
uint256 _amount2,
address _token2,
bool _forceUpdateGlobalExitRoot2,
bytes calldata _permitData2
) public {
// Set first bridge transaction parameters
destinationNetwork1 = _destinationNetwork1;
destinationAddress1 = _destinationAddress1;
amount1 = _amount1;
token1 = _token1;
forceUpdateGlobalExitRoot1 = _forceUpdateGlobalExitRoot1;
permitData1 = _permitData1;

// Set second bridge transaction parameters
destinationNetwork2 = _destinationNetwork2;
destinationAddress2 = _destinationAddress2;
amount2 = _amount2;
token2 = _token2;
forceUpdateGlobalExitRoot2 = _forceUpdateGlobalExitRoot2;
permitData2 = _permitData2;

emit UpdateBridgeParameters();
}

function onMessageReceived(
bytes memory data1
) external payable {
data = data1;

// First bridge transaction
try bridgeAddress.bridgeAsset{value: amount1}(
destinationNetwork1,
destinationAddress1,
amount1,
token1,
forceUpdateGlobalExitRoot1,
permitData1
) {
emit BridgeTransactionExecuted(destinationNetwork1, destinationAddress1, amount1);
} catch {
// First bridge transaction failed, continue with second transaction
}

// Second bridge transaction
try bridgeAddress.bridgeAsset{value: amount2}(
destinationNetwork2,
destinationAddress2,
amount2,
token2,
forceUpdateGlobalExitRoot2,
permitData2
) {
emit BridgeTransactionExecuted(destinationNetwork2, destinationAddress2, amount2);
} catch {
// Second bridge transaction failed, transaction continues
}

emit MessageReceived(msg.sender);
}

// Function to receive ETH
receive() external payable {}

// Fallback function
fallback() external payable {}
}
606 changes: 605 additions & 1 deletion core/contracts/bridgeAsset/InternalClaims.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion core/helpers/agglayer-cdk-common-setup.bash
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ _resolve_required_urls() {

# AGGKIT_BRIDGE_URL
aggkit_bridge_url=$(_resolve_url_or_use_env AGGKIT_BRIDGE_URL \
"aggkit-001-bridge" "rest" "cdk-node-001" "rest" \
"aggkit-001" "rest" "cdk-node-001" "rest" \

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rachit77 change this before merging

"Failed to resolve aggkit bridge url from all fallback nodes" true)
export aggkit_bridge_url

Expand Down
57 changes: 52 additions & 5 deletions core/helpers/scripts/aggkit_bridge_service.bash
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function bridge_asset() {
bridge_tx_hash=$(echo "$response" | grep "^transactionHash" | cut -f 2- -d ' ' | sed 's/ //g')
local bridge_tx_block_number
bridge_tx_block_number=$(echo "$response" | grep "^blockNumber" | cut -f 2- -d ' ' | sed 's/ //g')

if [[ -n "$bridge_tx_hash" ]]; then
log "🎉 Success: Tx Hash → $bridge_tx_hash (bn: $bridge_tx_block_number)"
echo "$bridge_tx_hash"
Expand Down Expand Up @@ -310,7 +310,7 @@ function wait_for_expected_token() {

# Fetch token mappings from the RPC
local cmd="curl -s -H \"Content-Type: application/json\" \"$aggkit_url/bridge/v1/token-mappings?network_id=$network_id\""

token_mappings_result=$(curl -s -H "Content-Type: application/json" "$aggkit_url/bridge/v1/token-mappings?network_id=$network_id")

# Extract the first origin_token_address (if available)
Expand All @@ -330,7 +330,7 @@ function wait_for_expected_token() {
if [[ "$attempt" -ge "$max_attempts" ]]; then
echo "❌ Error: Reached max attempts ($max_attempts) without finding expected origin_token_address." >&3
echo "❌ Error: Reached max attempts ($max_attempts) without finding expected origin_token_address." >&2
echo "command: $cmd"
echo "command: $cmd"
echo "--- token_mappings_result"
echo "$token_mappings_result"
echo "--- token_mappings_result"
Expand Down Expand Up @@ -440,7 +440,7 @@ function get_bridge() {

while ((attempt < max_attempts)); do
((attempt++))
log "🔎 $debug_msg Attempt $attempt/$max_attempts: fetching bridge \
log "🔎 $debug_msg Attempt $attempt/$max_attempts: fetching bridge \
(network id = $network_id, tx hash = $expected_tx_hash, bridge indexer url = $aggkit_url from_address=$from_address)"

# Build the query URL with optional from_address parameter
Expand Down Expand Up @@ -487,6 +487,53 @@ function get_bridge() {
return 1
}

function get_total_bridges() {
local network_id="$1"
local aggkit_url="$2"
local max_attempts="$3"
local poll_frequency="$4"

local attempt=0
local bridges_result=""

while ((attempt < max_attempts)); do
((attempt++))
log "🔎 Attempt $attempt/$max_attempts: fetching total bridges \
(network id = $network_id, bridge indexer url = $aggkit_url)"

# Capture both stdout (bridges result) and stderr (error message)
bridges_result=$(curl -s -H "Content-Type: application/json" \
"$aggkit_url/bridge/v1/bridges?network_id=$network_id" 2>&1)

# Check if the response contains an error
if [[ "$bridges_result" == *"error"* || "$bridges_result" == *"Error"* ]]; then
log "⚠️ Error: $bridges_result"
sleep "$poll_frequency"
continue
fi

if [[ "$bridges_result" == "" ]]; then
log "Empty bridges response retrieved, retrying in ${poll_frequency}s..."
sleep "$poll_frequency"
continue
fi

# Extract the total number of bridges
local total_bridges
total_bridges=$(echo "$bridges_result" | jq -r '.count')

if [[ "$total_bridges" != "null" && "$total_bridges" != "" ]]; then
echo "$total_bridges"
return 0
fi

sleep "$poll_frequency"
done

log "❌ Failed to find total bridges after $max_attempts attempts."
return 1
}

function log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >&3
}
Expand Down Expand Up @@ -670,7 +717,7 @@ function process_bridge_claim() {
local destination_aggkit_bridge_url="$7"
local destination_rpc_url="$8"
local from_address="${9:-}"


# 1. Fetch bridge details
local bridge
Expand Down
Loading
Loading