Skip to content
Open
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
f621f30
fix: remove gas airdrop logic
ChiTimesChi Apr 17, 2025
3b7545d
feat: allow governance to withdraw unspent gas airdops
ChiTimesChi Apr 17, 2025
2cde3ea
feat: add legacy flag
ChiTimesChi Apr 17, 2025
20b104d
test: coverage for legacy flagf
ChiTimesChi Apr 17, 2025
285d915
test: coverage for new gov actions
ChiTimesChi Apr 17, 2025
f778571
test: reenabling
ChiTimesChi Apr 17, 2025
e9bb701
chore: revert docs formatting changes
ChiTimesChi Apr 22, 2025
189b72e
chore: bump bridge version
ChiTimesChi Apr 23, 2025
acbcaa8
refactor: more explicit name for sending tokens
ChiTimesChi Apr 23, 2025
0f34b97
chore: update actions/cache@v2 to v4 in GitHub workflows
ChiTimesChi Apr 23, 2025
3407298
fix: update tests
ChiTimesChi Apr 23, 2025
84491d9
test: expected behaviour for mint/withdraw pre/post legacy workflows
ChiTimesChi May 30, 2025
2d66d69
feat: fallbacks to regular mint/withdraw
ChiTimesChi May 30, 2025
c314e1d
test: reentrancy cases
ChiTimesChi May 30, 2025
f9cda06
test: node group caller only
ChiTimesChi May 30, 2025
880b817
test: withdrawFees cases
ChiTimesChi May 30, 2025
82828e5
fix: reset fees before transfer
ChiTimesChi May 30, 2025
85d9566
fix: old repo tests (#338)
ChiTimesChi Jun 4, 2025
bd94918
Merge branch 'feat/syn-bridge-unified' into syn-100-legacy-workflows
ChiTimesChi Jun 4, 2025
f63c26d
refactor: better separation of security checks
ChiTimesChi Jun 4, 2025
ec6948b
Merge pull request #335 from synapsecns/syn-100-legacy-workflows
ChiTimesChi Jun 5, 2025
4616c2f
Merge branch 'feat/syn-bridge-unified' into syn-102-withdraw-fees
ChiTimesChi Jun 5, 2025
2b5e00a
Merge pull request #336 from synapsecns/syn-102-withdraw-fees
ChiTimesChi Jun 5, 2025
c35907c
SYN-106: minor suggestions (#337)
ChiTimesChi Jun 6, 2025
18b7fe9
Merge branch 'master' into feat/syn-bridge-unified
ChiTimesChi Jun 18, 2025
b7fb369
SYN-94: disable initializer in SynapseBridge implementation (#342)
ChiTimesChi Jun 27, 2025
a67c932
SYN-94: deploy script (#343)
ChiTimesChi Jun 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
94 changes: 76 additions & 18 deletions contracts/bridge/SynapseBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,26 @@ contract SynapseBridge is Initializable, AccessControlUpgradeable, ReentrancyGua
bytes32 public constant NODEGROUP_ROLE = keccak256("NODEGROUP_ROLE");
bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE");

uint256 public constant bridgeVersion = 8;
uint256 public constant chainGasAmount = 0;

mapping(address => uint256) private fees;

uint256 public startBlockNumber;
uint256 public constant bridgeVersion = 6;
uint256 public chainGasAmount;
/// @dev This is a variable taking the storage slot of deprecated chainGasAmount to prevent storage gap
uint256 private _deprecatedChainGasAmount;
address payable public WETH_ADDRESS;

mapping(bytes32 => bool) private kappaMap;
bool public isLegacySendDisabled;

modifier legacySendEnabled() {
require(!isLegacySendDisabled, "Legacy send is disabled");
_;
}

/// @dev We add initializer modifier to constructor to prevent implementation from being initialized
constructor() public initializer {}

receive() external payable {}

Expand All @@ -44,8 +56,20 @@ contract SynapseBridge is Initializable, AccessControlUpgradeable, ReentrancyGua
}

function setChainGasAmount(uint256 amount) external {
revert("Gas airdrop is disabled");
}

function withdrawChainGas() external {
require(hasRole(GOVERNANCE_ROLE, msg.sender), "Not governance");
chainGasAmount = amount;
emit ChainGasWithdrawn(msg.sender, address(this).balance);
(bool success, ) = msg.sender.call{value: address(this).balance}("");
require(success, "ETH_TRANSFER_FAILED");
}

function setLegacySendDisabled(bool _isLegacySendDisabled) external {
require(hasRole(GOVERNANCE_ROLE, msg.sender), "Not governance");
isLegacySendDisabled = _isLegacySendDisabled;
emit LegacySendDisabledSet(_isLegacySendDisabled);
}

function setWethAddress(address payable _wethAddress) external {
Expand Down Expand Up @@ -120,6 +144,10 @@ contract SynapseBridge is Initializable, AccessControlUpgradeable, ReentrancyGua
// v2 events
event TokenRedeemV2(bytes32 indexed to, uint256 chainId, IERC20 token, uint256 amount);

// New governance events
event LegacySendDisabledSet(bool isDisabled);
event ChainGasWithdrawn(address to, uint256 amount);

// VIEW FUNCTIONS ***/
function getFeeBalance(address tokenAddress) external view returns (uint256) {
return fees[tokenAddress];
Expand All @@ -138,9 +166,10 @@ contract SynapseBridge is Initializable, AccessControlUpgradeable, ReentrancyGua
function withdrawFees(IERC20 token, address to) external whenNotPaused {
require(hasRole(GOVERNANCE_ROLE, msg.sender), "Not governance");
require(to != address(0), "Address is 0x000");
if (fees[address(token)] != 0) {
token.safeTransfer(to, fees[address(token)]);
uint256 amount = fees[address(token)];
if (amount != 0) {
fees[address(token)] = 0;
token.safeTransfer(to, amount);
}
}

Expand All @@ -167,7 +196,7 @@ contract SynapseBridge is Initializable, AccessControlUpgradeable, ReentrancyGua
uint256 chainId,
IERC20 token,
uint256 amount
) external nonReentrant whenNotPaused {
) external nonReentrant whenNotPaused legacySendEnabled {
emit TokenDeposit(to, chainId, token, amount);
token.safeTransferFrom(msg.sender, address(this), amount);
}
Expand All @@ -184,7 +213,7 @@ contract SynapseBridge is Initializable, AccessControlUpgradeable, ReentrancyGua
uint256 chainId,
ERC20Burnable token,
uint256 amount
) external nonReentrant whenNotPaused {
) external nonReentrant whenNotPaused legacySendEnabled {
emit TokenRedeem(to, chainId, token, amount);
token.burnFrom(msg.sender, amount);
}
Expand All @@ -207,6 +236,20 @@ contract SynapseBridge is Initializable, AccessControlUpgradeable, ReentrancyGua
require(hasRole(NODEGROUP_ROLE, msg.sender), "Caller is not a node group");
require(amount > fee, "Amount must be greater than fee");
require(!kappaMap[kappa], "Kappa is already present");
_withdraw(to, token, amount, fee, kappa);
}

/**
* @dev Common internal logic for withdraw and withdrawAndRemove (once legacy workflows are disabled).
* Note: all security checks are handled outside of this function.
*/
function _withdraw(
address to,
IERC20 token,
uint256 amount,
uint256 fee,
bytes32 kappa
) internal {
kappaMap[kappa] = true;
fees[address(token)] = fees[address(token)].add(fee);
if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {
Expand Down Expand Up @@ -239,14 +282,25 @@ contract SynapseBridge is Initializable, AccessControlUpgradeable, ReentrancyGua
require(hasRole(NODEGROUP_ROLE, msg.sender), "Caller is not a node group");
require(amount > fee, "Amount must be greater than fee");
require(!kappaMap[kappa], "Kappa is already present");
_mint(to, token, amount, fee, kappa);
}

/**
* @dev Common internal logic for mint and mintAndSwap (once legacy workflows are disabled).
* Note: all security checks are handled outside of this function.
*/
function _mint(
address payable to,
IERC20Mintable token,
uint256 amount,
uint256 fee,
bytes32 kappa
) internal {
kappaMap[kappa] = true;
fees[address(token)] = fees[address(token)].add(fee);
emit TokenMint(to, token, amount.sub(fee), fee, kappa);
token.mint(address(this), amount);
IERC20(token).safeTransfer(to, amount.sub(fee));
if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {
to.call.value(chainGasAmount)("");
}
}

/**
Expand All @@ -269,7 +323,7 @@ contract SynapseBridge is Initializable, AccessControlUpgradeable, ReentrancyGua
uint8 tokenIndexTo,
uint256 minDy,
uint256 deadline
) external nonReentrant whenNotPaused {
) external nonReentrant whenNotPaused legacySendEnabled {
emit TokenDepositAndSwap(to, chainId, token, amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);
token.safeTransferFrom(msg.sender, address(this), amount);
}
Expand All @@ -294,7 +348,7 @@ contract SynapseBridge is Initializable, AccessControlUpgradeable, ReentrancyGua
uint8 tokenIndexTo,
uint256 minDy,
uint256 deadline
) external nonReentrant whenNotPaused {
) external nonReentrant whenNotPaused legacySendEnabled {
emit TokenRedeemAndSwap(to, chainId, token, amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);
token.burnFrom(msg.sender, amount);
}
Expand All @@ -317,7 +371,7 @@ contract SynapseBridge is Initializable, AccessControlUpgradeable, ReentrancyGua
uint8 swapTokenIndex,
uint256 swapMinAmount,
uint256 swapDeadline
) external nonReentrant whenNotPaused {
) external nonReentrant whenNotPaused legacySendEnabled {
emit TokenRedeemAndRemove(to, chainId, token, amount, swapTokenIndex, swapMinAmount, swapDeadline);
token.burnFrom(msg.sender, amount);
}
Expand Down Expand Up @@ -351,12 +405,12 @@ contract SynapseBridge is Initializable, AccessControlUpgradeable, ReentrancyGua
require(hasRole(NODEGROUP_ROLE, msg.sender), "Caller is not a node group");
require(amount > fee, "Amount must be greater than fee");
require(!kappaMap[kappa], "Kappa is already present");
// Fallback to regular mint if legacy workflows are disabled.
if (isLegacySendDisabled) {
return _mint(to, token, amount, fee, kappa);
}
kappaMap[kappa] = true;
fees[address(token)] = fees[address(token)].add(fee);
// Transfer gas airdrop
if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {
to.call.value(chainGasAmount)("");
}
// first check to make sure more will be given than min amount required
uint256 expectedOutput = ISwap(pool).calculateSwap(tokenIndexFrom, tokenIndexTo, amount.sub(fee));

Expand Down Expand Up @@ -459,6 +513,10 @@ contract SynapseBridge is Initializable, AccessControlUpgradeable, ReentrancyGua
require(hasRole(NODEGROUP_ROLE, msg.sender), "Caller is not a node group");
require(amount > fee, "Amount must be greater than fee");
require(!kappaMap[kappa], "Kappa is already present");
// Fallback to regular withdraw if legacy workflows are disabled.
if (isLegacySendDisabled) {
return _withdraw(to, token, amount, fee, kappa);
}
kappaMap[kappa] = true;
fees[address(token)] = fees[address(token)].add(fee);
// first check to make sure more will be given than min amount required
Expand Down Expand Up @@ -526,7 +584,7 @@ contract SynapseBridge is Initializable, AccessControlUpgradeable, ReentrancyGua
uint256 chainId,
ERC20Burnable token,
uint256 amount
) external nonReentrant whenNotPaused {
) external nonReentrant whenNotPaused legacySendEnabled {
emit TokenRedeemV2(to, chainId, token, amount);
token.burnFrom(msg.sender, amount);
}
Expand Down
42 changes: 21 additions & 21 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,30 +52,30 @@ op_sepolia = "${OP_SEPOLIA_API}"
scroll_sepolia = "${SCROLL_SEPOLIA_API}"

[etherscan]
arbitrum = { key = "${ARBITRUM_ETHERSCAN_KEY}", url = "${ARBITRUM_ETHERSCAN_URL}" }
# TODO: find out if this is correct
aurora = { key = "", url = "${AURORA_BLOCKSCOUT_URL}" }
avalanche = { key = "${AVALANCHE_ETHERSCAN_KEY}", url = "${AVALANCHE_ETHERSCAN_URL}" }
base = { key = "${BASE_ETHERSCAN_KEY}", url = "${BASE_ETHERSCAN_URL}" }
blast = { key = "${BLAST_ETHERSCAN_KEY}", url = "${BLAST_ETHERSCAN_URL}" }
boba = { key = "${BOBA_ETHERSCAN_KEY}", url = "${BOBA_ETHERSCAN_URL}" }
bsc = { key = "${BSC_ETHERSCAN_KEY}", url = "${BSC_ETHERSCAN_URL}" }
canto = { key = "", url = "${CANTO_BLOCKSCOUT_URL}" }
cronos = { key = "${CRONOS_ETHERSCAN_KEY}", url = "${CRONOS_ETHERSCAN_URL}" }
# Chains that are not currently using etherscan are commented out
arbitrum = { key = "${ARBITRUM_ETHERSCAN_KEY}", url = "${ARBITRUM_ETHERSCAN_URL}", chain = 42161 }
# aurora = { key = "", url = "${AURORA_BLOCKSCOUT_URL}" }
avalanche = { key = "${AVALANCHE_ETHERSCAN_KEY}", url = "${AVALANCHE_ETHERSCAN_URL}", chain = 43114 }
base = { key = "${BASE_ETHERSCAN_KEY}", url = "${BASE_ETHERSCAN_URL}", chain = 8453 }
blast = { key = "${BLAST_ETHERSCAN_KEY}", url = "${BLAST_ETHERSCAN_URL}", chain = 81457 }
# boba = { key = "${BOBA_ETHERSCAN_KEY}", url = "${BOBA_ETHERSCAN_URL}" }
bsc = { key = "${BSC_ETHERSCAN_KEY}", url = "${BSC_ETHERSCAN_URL}", chain = 56 }
# canto = { key = "", url = "${CANTO_BLOCKSCOUT_URL}" }
cronos = { key = "${CRONOS_ETHERSCAN_KEY}", url = "${CRONOS_ETHERSCAN_URL}", chain = 25 }
# DFK is using Sourcify for verification
dogechain = { key = "", url = "${DOGECHAIN_BLOCKSCOUT_URL}" }
fantom = { key = "${FANTOM_ETHERSCAN_KEY}", url = "${FANTOM_ETHERSCAN_URL}" }
# dogechain = { key = "", url = "${DOGECHAIN_BLOCKSCOUT_URL}" }
# fantom = { key = "${FANTOM_ETHERSCAN_KEY}", url = "${FANTOM_ETHERSCAN_URL}" }
# Harmony doesn't have an endpoint for verification, and Sourcify does not support Harmony
# Klaytn doesn't have an endpoint for verification, and doesn't support Sourcify yet
linea = { key = "${LINEA_ETHERSCAN_KEY}", url = "${LINEA_ETHERSCAN_URL}" }
mainnet = { key = "${MAINNET_ETHERSCAN_KEY}", url = "${MAINNET_ETHERSCAN_URL}" }
metis = { key = "", url = "${METIS_BLOCKSCOUT_URL}" }
moonbeam = { key = "${MOONBEAM_ETHERSCAN_KEY}", url = "${MOONBEAM_ETHERSCAN_URL}" }
moonriver = { key = "${MOONRIVER_ETHERSCAN_KEY}", url = "${MOONRIVER_ETHERSCAN_URL}" }
optimism = { key = "${OPTIMISM_ETHERSCAN_KEY}", url = "${OPTIMISM_ETHERSCAN_URL}" }
polygon = { key = "${POLYGON_ETHERSCAN_KEY}", url = "${POLYGON_ETHERSCAN_URL}" }
scroll = { key = "${SCROLL_ETHERSCAN_KEY}", url = "${SCROLL_ETHERSCAN_URL}" }
zkevm = { key = "${ZKEVM_ETHERSCAN_KEY}", url = "${ZKEVM_ETHERSCAN_URL}" }
linea = { key = "${LINEA_ETHERSCAN_KEY}", url = "${LINEA_ETHERSCAN_URL}", chain = 59144 }
mainnet = { key = "${MAINNET_ETHERSCAN_KEY}", url = "${MAINNET_ETHERSCAN_URL}", chain = 1 }
# metis = { key = "", url = "${METIS_BLOCKSCOUT_URL}" }
moonbeam = { key = "${MOONBEAM_ETHERSCAN_KEY}", url = "${MOONBEAM_ETHERSCAN_URL}", chain = 1284 }
moonriver = { key = "${MOONRIVER_ETHERSCAN_KEY}", url = "${MOONRIVER_ETHERSCAN_URL}", chain = 1285 }
optimism = { key = "${OPTIMISM_ETHERSCAN_KEY}", url = "${OPTIMISM_ETHERSCAN_URL}", chain = 10 }
polygon = { key = "${POLYGON_ETHERSCAN_KEY}", url = "${POLYGON_ETHERSCAN_URL}", chain = 137 }
scroll = { key = "${SCROLL_ETHERSCAN_KEY}", url = "${SCROLL_ETHERSCAN_URL}", chain = 534532 }
zkevm = { key = "${ZKEVM_ETHERSCAN_KEY}", url = "${ZKEVM_ETHERSCAN_URL}", chain = 1101 }
# Testnets
arb_sepolia = { key = "${ARB_SEPOLIA_ETHERSCAN_KEY}", url = "${ARB_SEPOLIA_ETHERSCAN_URL}" }
base_sepolia = { key = "${BASE_SEPOLIA_ETHERSCAN_KEY}", url = "${BASE_SEPOLIA_ETHERSCAN_URL}" }
Expand Down
38 changes: 38 additions & 0 deletions script/bridge/DeploySynapseBridge.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

import {SynapseBridge} from "../../contracts/bridge/SynapseBridge.sol";

import {BasicSynapseScript, StringUtils} from "../templates/BasicSynapse.s.sol";

contract DeploySynapseBridge is BasicSynapseScript {
using StringUtils for string;

// TODO: mine a create2 salt for this
bytes32 internal salt = 0;

function run() external {
// Setup the BasicSynapseScript
setUp();
address bridge = tryGetDeploymentAddress("SynapseBridge");
if (bridge == address(0)) {
printLog(StringUtils.concat("🟡 Skipping: SynapseBridge is not deployed on ", activeChain));
return;
}
vm.startBroadcast();
address predicted = predictAddress(type(SynapseBridge).creationCode, salt);
printLog(StringUtils.concat("Predicted address: ", vm.toString(predicted)));
address deployed = deployAndSaveAs({
contractName: "SynapseBridge",
contractAlias: "SynapseBridge.Implementation",
constructorArgs: "",
deployCode: deployCreate2
});
if (predicted != deployed) {
printLog(TAB.concat("❌ Predicted address mismatch"));
assert(false);
}
vm.stopBroadcast();
}
}
29 changes: 29 additions & 0 deletions script/bridge/deploy-implementation.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
# This script deploys the SynapseBridge implementation on all chains
# Usage: ./script/bridge/deploy-implementation.sh <walletName> [<args...>]
# - <walletName> name of the wallet to use for deployment

# Colors
RED="\033[0;31m"
NC="\033[0m" # No Color

WALLET_NAME=$1
# Get the rest of the args
shift 1
# Check that all required args exist
if [ -z "$WALLET_NAME" ]; then
echo -e "${RED}Usage: ./script/bridge/deploy-implementation.sh <walletName> [<args...>]${NC}"
exit 1
fi

# Make sure the script is run from the root of the project
PROJECT_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")"/../../ && pwd)
cd "$PROJECT_ROOT" || exit 1

# Run the script on all chains with SynapseBridge deployment
# Look within deployments/chainName for SynapseBridge.json
for chainName in $(ls deployments); do
if [ -f "deployments/$chainName/SynapseBridge.json" ]; then
./script/run.sh ./script/bridge/DeploySynapseBridge.s.sol "$chainName" "$WALLET_NAME" "$@"
fi
done
Comment on lines +25 to +29
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Fix: Use robust iteration pattern instead of ls output.

The current approach of iterating over ls output can be fragile with filenames containing spaces or special characters.

-for chainName in $(ls deployments); do
+for chainName in deployments/*/; do
+  chainName=$(basename "$chainName")
   if [ -f "deployments/$chainName/SynapseBridge.json" ]; then
     ./script/run.sh ./script/bridge/DeploySynapseBridge.s.sol "$chainName" "$WALLET_NAME" "$@"
   fi
 done
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for chainName in $(ls deployments); do
if [ -f "deployments/$chainName/SynapseBridge.json" ]; then
./script/run.sh ./script/bridge/DeploySynapseBridge.s.sol "$chainName" "$WALLET_NAME" "$@"
fi
done
for chainName in deployments/*/; do
chainName=$(basename "$chainName")
if [ -f "deployments/$chainName/SynapseBridge.json" ]; then
./script/run.sh ./script/bridge/DeploySynapseBridge.s.sol "$chainName" "$WALLET_NAME" "$@"
fi
done
🧰 Tools
🪛 Shellcheck (0.10.0)

[error] 25-25: Iterating over ls output is fragile. Use globs.

(SC2045)

🤖 Prompt for AI Agents
In script/bridge/deploy-implementation.sh around lines 25 to 29, replace the for
loop that iterates over the output of `ls deployments` with a more robust
pattern such as a glob pattern or a while loop using `find` or `readarray` to
safely handle directory names with spaces or special characters. This avoids
issues caused by word splitting and ensures reliable iteration over the
deployment directories.

6 changes: 3 additions & 3 deletions script/templates/BasicUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,11 @@ abstract contract BasicUtils is CommonBase {
string memory pathOutput,
string memory key
) internal returns (string memory fullInputData) {
// Example: jq .abi=$data.abi --argfile data path/to/input.json path/to/output.json
// Example: jq .abi=$data[0].abi --slurpfile data path/to/input.json path/to/output.json
string[] memory inputs = new string[](6);
inputs[0] = "jq";
inputs[1] = key.concat(" = $data", key);
inputs[2] = "--argfile";
inputs[1] = key.concat(" = $data[0]", key);
inputs[2] = "--slurpfile";
Comment on lines +278 to +282
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify the JSON structure change is consistent across the codebase.

The change from --argfile to --slurpfile with array access ($data[0]) suggests the input JSON structure has changed from a single object to an array format. Ensure this change aligns with how JSON artifacts are generated and consumed elsewhere in the codebase.


🏁 Script executed:

#!/bin/bash
# Verify usage of addJsonKey function and related JSON processing
rg -A 3 -B 3 "addJsonKey|--argfile|--slurpfile" --type sol --type sh

Length of output: 98


To ensure we capture all occurrences regardless of file-type mappings, let’s drop the --type filters and use globs instead:


🏁 Script executed:

#!/bin/bash
# Search for JSON key helper usage and jq flags across Solidity and shell scripts
rg -A3 -B3 "addJsonKey|--argfile|--slurpfile" -g '*.sol' -g '*.sh'

Length of output: 2567


Inconsistent jq flag usage in DeployScript.sol

The helper in BasicUtils.sol now uses --slurpfile with array indexing ($data[0]), but script/utils/DeployScript.sol still uses --argfile and accesses $artifact.abi. This will break JSON handling. Please update:

• File: script/utils/DeployScript.sol

--- a/script/utils/DeployScript.sol
@@ (inside function that builds jq inputs)
- inputs[1] = "--argfile";
+ inputs[1] = "--slurpfile";
  inputs[2] = "artifact";
  inputs[3] = _artifactPath(contractName);
- inputs[4] = ".abi = $artifact.abi";
+ inputs[4] = ".abi = $artifact[0].abi";
  inputs[5] = path;

This aligns both scripts to handle the input JSON as an array.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Example: jq .abi=$data[0].abi --slurpfile data path/to/input.json path/to/output.json
string[] memory inputs = new string[](6);
inputs[0] = "jq";
inputs[1] = key.concat(" = $data", key);
inputs[2] = "--argfile";
inputs[1] = key.concat(" = $data[0]", key);
inputs[2] = "--slurpfile";
// inside function that builds jq inputs in script/utils/DeployScript.sol
inputs[1] = "--slurpfile";
inputs[2] = "artifact";
inputs[3] = _artifactPath(contractName);
inputs[4] = ".abi = $artifact[0].abi";
inputs[5] = path;
🤖 Prompt for AI Agents
In script/utils/DeployScript.sol around the lines where jq is used with
--argfile and $artifact.abi, update the jq command to use --slurpfile instead of
--argfile and change the JSON access from $artifact.abi to $data[0].abi to match
the array handling in BasicUtils.sol. This ensures consistent JSON input
handling across both scripts.

inputs[3] = "data";
inputs[4] = pathInput;
inputs[5] = pathOutput;
Expand Down
16 changes: 16 additions & 0 deletions test/bridge/legacy/PoolMock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;

// solhint-disable no-empty-blocks, no-unused-vars
contract PoolMock {
/// @notice We include an empty "test" function so that this contract does not appear in the coverage report.
function testPoolMock() external {}

function calculateSwap(
uint8 tokenIndexFrom,
uint8 tokenIndexTo,
uint256 amount
) external returns (uint256) {}

function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external returns (uint256) {}
}
Loading
Loading