Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
95078d9
Collateral and Discovery tests
Hakob23 Oct 26, 2025
2b273dc
Add comprehensive tests for PegIn
Hakob23 Oct 27, 2025
01a5d6f
Add tests for PegOut functionality
Hakob23 Oct 27, 2025
7424888
Add integration and legacy tests
Hakob23 Oct 28, 2025
47cf6b3
Refactor test formatting
Hakob23 Oct 28, 2025
ff951df
Update import paths in tests and add remapping for contracts in found…
Hakob23 Oct 28, 2025
03760e6
refactor deployment scripts
Hakob23 Nov 4, 2025
6850d29
refactor foundry tasks
Hakob23 Nov 4, 2025
6d2e06c
Add hash-quote functionality with FFI support for Bitcoin address par…
Hakob23 Nov 5, 2025
b133bfa
Add pause and unpause functionality for system contracts with corresp…
Hakob23 Nov 9, 2025
c72d5f7
Add refund-user-pegout functionality with simulation and broadcast mo…
Hakob23 Nov 9, 2025
bb98036
Add register-pegin functionality with simulation and broadcast modes,…
Hakob23 Nov 9, 2025
d20c3e6
Add deployment tests for ChangeOwnerToMultiSig, DeployLBC, PrepareUpg…
Hakob23 Nov 9, 2025
e6bfc7a
Refactor Makefile to replace bash scripts with Foundry scripts for ha…
Hakob23 Nov 9, 2025
28a4e8f
style formatting
Hakob23 Nov 9, 2025
fd3e2fb
Add new helper scripts for fetching Bitcoin transaction data and pars…
Hakob23 Nov 9, 2025
0419ede
Except specific revert and event messages for Configuration.t.sol
Hakob23 Nov 12, 2025
5a8eee4
use interface error definitions directly
Hakob23 Nov 12, 2025
d3a3f76
Add event emission expectations
Hakob23 Nov 12, 2025
c1ba179
Add penalty and reward calculations in LpRefund tests, including even…
Hakob23 Nov 12, 2025
214fbd7
Add TypeScript helper scripts for generating Bitcoin transactions and…
Hakob23 Nov 12, 2025
8704283
Rename test for malformed Bitcoin transaction and add new test for in…
Hakob23 Nov 13, 2025
7c8f0e4
Add comprehensive tests for PegInQuote and PegOutQuote hash calculati…
Hakob23 Nov 13, 2025
a8fcdf5
Enhance Deposit and LpRefund tests with BTC mock initialization quote…
Hakob23 Nov 13, 2025
9fd1774
Refactor deposit peg-out test names for clarity and add new tests for…
Hakob23 Nov 13, 2025
b321bff
Reentrancy check
Hakob23 Nov 13, 2025
d55390b
Add event emission expectations for PegIn registration and refunds in…
Hakob23 Nov 14, 2025
54668ea
Add reentrancy test for refund failure in RegisterPegIn, verifying in…
Hakob23 Nov 14, 2025
0912570
Expect specific revert messages and event emissions
Hakob23 Nov 14, 2025
79207d7
Refactor DerivationAddress to included hardcoded address checks as in…
Hakob23 Nov 15, 2025
07aa67a
adding missing tests
Hakob23 Nov 15, 2025
5414562
Update event emission expectations in Registration tests to reflect c…
Hakob23 Nov 17, 2025
a219de5
Add ownership transfer tests to verify new owner operations and rever…
Hakob23 Nov 17, 2025
ddf7381
verify non-pausable functions continue to operate during contract pauses
Hakob23 Nov 17, 2025
6b459bb
Add comprehensive tests for PauseSystem to verify contract pause stat…
Hakob23 Nov 17, 2025
9e892ff
Refactor gas estimation in RefundUserPegout
Hakob23 Nov 17, 2025
bb0ad1a
Add BtcAddressParser library and refactor HashQuote and RegisterPegin…
Hakob23 Nov 17, 2025
467c958
style refactor
Hakob23 Nov 17, 2025
eefcbe3
Refactor Makefile to remove USE_LEDGER conditionals
Hakob23 Nov 18, 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
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ node_modules
errorCodes.json
coverage/
coverage.json
out/
forge-cache/
291 changes: 282 additions & 9 deletions Makefile

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export default [
"artifacts/*",
"cache/*",
"coverage/*",
"broadcast/*",
"out/*",
"forge-cache/*",
],
},
pluginJs.configs.recommended,
Expand Down
2 changes: 1 addition & 1 deletion forge-scripts/HelperConfig.s.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {Script} from "forge-std/Script.sol";
import {Script} from "lib/forge-std/src/Script.sol";
import {BridgeMock} from "../contracts/test-contracts/BridgeMock.sol";

contract HelperConfig is Script {
Expand Down
66 changes: 0 additions & 66 deletions forge-scripts/UpgradeLBC.s.sol

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ pragma solidity 0.8.25;
* @author Generated for Liquidity Bridge Contract
*/

import {Script, console} from "forge-std/Script.sol";
import {HelperConfig} from "./HelperConfig.s.sol";
import {LiquidityBridgeContractV2} from "../contracts/legacy/LiquidityBridgeContractV2.sol";
import {LiquidityBridgeContractAdmin} from "../contracts/legacy/LiquidityBridgeContractAdmin.sol";
import {Script, console} from "lib/forge-std/src/Script.sol";
import {HelperConfig} from "../../forge-scripts/HelperConfig.s.sol";
import {LiquidityBridgeContractV2} from "../../contracts/legacy/LiquidityBridgeContractV2.sol";
import {LiquidityBridgeContractAdmin} from "../../contracts/legacy/LiquidityBridgeContractAdmin.sol";
import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";

interface IGnosisSafe {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {Script, console} from "forge-std/Script.sol";
import {Script, console} from "lib/forge-std/src/Script.sol";

import {HelperConfig} from "./HelperConfig.s.sol";
import {HelperConfig} from "../HelperConfig.s.sol";

import {LiquidityBridgeContract} from "../contracts/legacy/LiquidityBridgeContract.sol";
import {LiquidityBridgeContractProxy} from "../contracts/legacy/LiquidityBridgeContractProxy.sol";
import {LiquidityBridgeContractAdmin} from "../contracts/legacy/LiquidityBridgeContractAdmin.sol";
import {LiquidityBridgeContract} from "../../contracts/legacy/LiquidityBridgeContract.sol";
import {LiquidityBridgeContractProxy} from "../../contracts/legacy/LiquidityBridgeContractProxy.sol";
import {LiquidityBridgeContractAdmin} from "../../contracts/legacy/LiquidityBridgeContractAdmin.sol";

contract DeployLBC is Script {
function run() external {
Expand Down
44 changes: 44 additions & 0 deletions forge-scripts/deployment/PrepareUpgrade.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {Script, console} from "lib/forge-std/src/Script.sol";

import {HelperConfig} from "../HelperConfig.s.sol";
import {LiquidityBridgeContractV2} from "../../contracts/legacy/LiquidityBridgeContractV2.sol";

/**
* @title PrepareUpgrade
* @notice Deploys the V2 implementation WITHOUT upgrading the proxy
* @dev This allows for a two-step upgrade process:
* 1. Deploy and verify the implementation (this script)
* 2. Perform the actual upgrade (UpgradeLBC script)
*
* Usage:
* make prepare-upgrade NETWORK=testnet
*/
contract PrepareUpgrade is Script {
function run() external {
HelperConfig helper = new HelperConfig();

uint256 deployerKey = helper.getDeployerPrivateKey();
vm.rememberKey(deployerKey);

vm.startBroadcast(deployerKey);

console.log(
"=== Deploying LiquidityBridgeContractV2 implementation ==="
);

// Deploy new V2 implementation (libraries are linked via command line)
LiquidityBridgeContractV2 newImplementation = new LiquidityBridgeContractV2();

console.log("IMPLEMENTATION ADDRESS:", address(newImplementation));
console.log("");
console.log("Next step:");
console.log(
"Run the upgrade script: make upgrade-lbc NETWORK=<network>"
);

vm.stopBroadcast();
}
}
114 changes: 114 additions & 0 deletions forge-scripts/deployment/UpgradeLBC.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {Script, console} from "lib/forge-std/src/Script.sol";

import {HelperConfig} from "../HelperConfig.s.sol";

import {LiquidityBridgeContractV2} from "../../contracts/legacy/LiquidityBridgeContractV2.sol";
import {LiquidityBridgeContractAdmin} from "../../contracts/legacy/LiquidityBridgeContractAdmin.sol";
import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";

/**
* @title UpgradeLBC
* @notice Upgrades the LiquidityBridgeContract proxy to V2
* @dev Supports two workflows:
* 1. Deploy implementation and upgrade in one transaction (default)
* 2. Upgrade to a pre-deployed implementation (set IMPLEMENTATION_ADDRESS env var)
*
* Usage:
* # Deploy + Upgrade:
* make upgrade-lbc NETWORK=testnet
*
* # Upgrade to existing implementation:
* IMPLEMENTATION_ADDRESS=0x... make upgrade-lbc NETWORK=testnet
*/
contract UpgradeLBC is Script {
function run() external {
HelperConfig helper = new HelperConfig();
HelperConfig.NetworkConfig memory cfg = helper.getConfig();

uint256 deployerKey = helper.getDeployerPrivateKey();
vm.rememberKey(deployerKey);

// Get the existing proxy and admin addresses from environment or config
address proxyAddress = cfg.existingProxy;
address wrapperAddress = cfg.existingAdmin;

require(proxyAddress != address(0), "Proxy address must be provided");
require(
wrapperAddress != address(0),
"Admin wrapper address must be provided"
);

vm.startBroadcast(deployerKey);

// Check if we should use a pre-deployed implementation
address implementationAddress;
try vm.envAddress("IMPLEMENTATION_ADDRESS") returns (address addr) {
implementationAddress = addr;
console.log("=== Using pre-deployed implementation ===");
console.log("Implementation address:", implementationAddress);
} catch {
console.log("=== Deploying new implementation ===");
// Deploy new V2 implementation (libraries are linked via command line)
LiquidityBridgeContractV2 newImplementation = new LiquidityBridgeContractV2();
implementationAddress = address(newImplementation);
console.log(
"LiquidityBridgeContractV2 implementation:",
implementationAddress
);
}

// Get the actual ProxyAdmin address from the proxy
address proxyAdminAddress = address(
uint160(
uint256(
vm.load(
proxyAddress,
bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1)
)
)
)
);
console.log("ProxyAdmin address:", proxyAdminAddress);

// Get the ProxyAdmin contract instance
LiquidityBridgeContractAdmin admin = LiquidityBridgeContractAdmin(
proxyAdminAddress
);

// Get the owner of the ProxyAdmin (should be the wrapper)
address adminOwner = admin.owner();
console.log("ProxyAdmin owner:", adminOwner);

vm.stopBroadcast();

// Impersonate the ProxyAdmin owner to call upgradeAndCall
// This works in simulation/fork mode for testing
vm.startPrank(adminOwner);

// Upgrade the proxy to point to the new implementation
// Note: Pass empty bytes - no initialization needed on upgrade (initializeV2 can only be called once)
admin.upgradeAndCall(
ITransparentUpgradeableProxy(proxyAddress),
implementationAddress,
""
);

vm.stopPrank();

console.log("Proxy upgraded successfully");
console.log("Proxy address:", proxyAddress);
console.log("New implementation:", implementationAddress);

// Verify the upgrade by checking the version
LiquidityBridgeContractV2 upgradedContract = LiquidityBridgeContractV2(
payable(proxyAddress)
);
console.log(
"Contract version after upgrade:",
upgradedContract.version()
);
}
}
56 changes: 56 additions & 0 deletions forge-scripts/helpers/BtcAddressParser.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {Vm} from "lib/forge-std/src/Vm.sol";

library BtcAddressParserLib {
string constant HELPER_SCRIPT_BTC_ADDRESS =
"forge-scripts/helpers/parse-btc-address.ts";

function parseBtcAddress(
Vm vm,
string memory btcAddress
) internal returns (bytes memory) {
string[] memory inputs = new string[](4);
inputs[0] = "npx";
inputs[1] = "ts-node";
inputs[2] = HELPER_SCRIPT_BTC_ADDRESS;
inputs[3] = btcAddress;

bytes memory result = vm.ffi(inputs);
return result;
}

function parseFedBtcAddress(
Vm vm,
string memory btcAddress
) internal returns (bytes20) {
bytes memory decoded = parseBtcAddress(vm, btcAddress);
require(decoded.length >= 21, "Invalid fedBtcAddress length");

bytes memory sliced = new bytes(20);
for (uint i = 0; i < 20; i++) {
sliced[i] = decoded[i + 1];
}

return bytes20(sliced);
}
}

abstract contract BtcAddressParser {
function _getVm() internal pure returns (Vm) {
return Vm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
}

function parseBtcAddress(
string memory btcAddress
) internal returns (bytes memory) {
return BtcAddressParserLib.parseBtcAddress(_getVm(), btcAddress);
}

function parseFedBtcAddress(
string memory btcAddress
) internal returns (bytes20) {
return BtcAddressParserLib.parseFedBtcAddress(_getVm(), btcAddress);
}
}
Loading