Skip to content
Closed
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
17 changes: 17 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
### Replace placeholder values before running scripts

# Private key used by forge script (hex without quotes)
PRIVATE_KEY=0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd

# External RPC endpoint to broadcast transactions
RPC_URL=https://rpc.testnet3.goat.network

# Previously deployed Bitcoin SPV verifier contract
BITCOINSPV_ADDR=0x0000000000000000000000000000000000000001

# Committee member addresses (add or remove sequentially numbered keys)
COMMITTEE_0=0x0000000000000000000000000000000000000001
COMMITTEE_1=0x0000000000000000000000000000000000000002

# Watchtower identifiers (32-byte hex strings). Add WATCHTOWER_2, etc. as needed.
WATCHTOWER_0=0x0000000000000000000000000000000000000000000000000000000000000001
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
deployMain:
forge script script/DeployGateway.sol:DeployGateway --rpc-url goatMainnet --broadcast -vvvv --verify --verifier blockscout --verifier-url https://explorer.goat.network/api/

deployTest:
forge script script/DeployGateway.sol:DeployGateway --rpc-url goatTestnet --broadcast -vvvv --verify --verifier blockscout --verifier-url https://explorer.testnet3.goat.network/api/

8 changes: 8 additions & 0 deletions foundry.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"lib/openzeppelin-contracts-upgradeable": {
"rev": "3d5fa5c24c411112bab47bec25cfa9ad0af0e6e8"
},
"lib/forge-std": {
"rev": "3b20d60d14b343ee4f908cb8079495c07f5e8981"
}
}
37 changes: 37 additions & 0 deletions script/CommitteeRegisterPeerId.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

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

/*
Script: Register a peer ID for the committee.
Required env vars:
- PRIVATE_KEY: uint256 private key to broadcast from (committee member)
- GATEWAY_ADDR: address of deployed Gateway (proxy)
- PEER_ID: bytes peer ID to register
*/
contract RegisterPeerId is Script {
function run() public {
uint256 committeePrivateKey = vm.envUint("PRIVATE_KEY");
address committee = vm.addr(committeePrivateKey);

address gatewayAddr = vm.envAddress("GATEWAY_ADDR");
address committeeManagementAddr = address(GatewayUpgradeable(payable(gatewayAddr)).committeeManagement());
bytes memory peerId = vm.envBytes("PEER_ID");

console.log("Committee:", committee);
console.log("Gateway:", gatewayAddr);
console.log("Committee Management:", committeeManagementAddr);
console.log("Peer ID:", vm.toString(peerId));

vm.startBroadcast(committeePrivateKey);

CommitteeManagement(committeeManagementAddr).registerPeerId(peerId);

console.log("Peer ID registered successfully");

vm.stopBroadcast();
}
}
36 changes: 0 additions & 36 deletions script/DebugCancelWithdraw.sol

This file was deleted.

41 changes: 0 additions & 41 deletions script/DebugMintPegBTC.sol

This file was deleted.

117 changes: 91 additions & 26 deletions script/DeployContractDebug.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,20 @@ import {IPegBTC} from "../src/interfaces/IPegBTC.sol";
import {IBitcoinSPV} from "../src/interfaces/IBitcoinSPV.sol";
import {CommitteeManagement} from "../src/CommitteeManagement.sol";
import {StakeManagement} from "../src/StakeManagement.sol";
import {ICommitteeManagement} from "../src/interfaces/ICommitteeManagement.sol";
import {IStakeManagement} from "../src/interfaces/IStakeManagement.sol";

import {GatewayDebug, CommitteeManagementDebug} from "../src/GatewayDebug.sol";
import {PegBTC} from "../src/PegBTC.sol";
import {UpgradeableProxy} from "../src/UpgradeableProxy.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

/*
Script: Deploy the GatewayDebug contract and related contracts.
Required env vars:
- PRIVATE_KEY: uint256 private key to broadcast from (deployer)
- BITCOINSPV_ADDR: address of the BitcoinSPV contract
*/
contract DeployGateway is Script {
address public deployer;
address public bitcoinSPV;
Expand All @@ -30,47 +38,97 @@ contract DeployGateway is Script {
}

function deploy() public {
// deploy contracts
GatewayDebug gatewayImpl = new GatewayDebug();
console.log("Gateway implementation contract address: ", address(gatewayImpl));
console.log(
"Gateway implementation contract address: ",
address(gatewayImpl)
);

UpgradeableProxy proxy = new UpgradeableProxy(address(gatewayImpl), deployer, "");
console.log("Gateway proxy contract contract address: ", address(proxy));
GatewayDebug gateway = GatewayDebug(payable(proxy));
UpgradeableProxy gatewayProxy = new UpgradeableProxy(
address(gatewayImpl),
deployer,
""
);
console.log("Gateway proxy contract address: ", address(gatewayProxy));
GatewayDebug gateway = GatewayDebug(payable(gatewayProxy));

PegBTC pegBTC = new PegBTC(address(gateway));
console.log("PegBTC contract address: ", address(pegBTC));

// Read committee config from env
// - COMMITTEE_0, COMMITTEE_1, ... (addresses)
// - WATCHTOWER_0, WATCHTOWER_1, ... (bytes32)
address[] memory initialMembers = _readSequentialAddresses("COMMITTEE");
uint256 initialRequired = (initialMembers.length * 2 + 2) / 3;
bytes32[] memory initialWatchtowers = _readSequentialBytes32("WATCHTOWER");
bytes32[] memory initialWatchtowers = _readSequentialBytes32(
"WATCHTOWER"
);
require(initialMembers.length > 0, "COMMITTEE list empty");
require(initialWatchtowers.length > 0, "WATCHTOWER list empty");
address[] memory initialAuthorizedCallers = new address[](1);
initialAuthorizedCallers[0] = address(gateway);
CommitteeManagementDebug committeeManagement =
new CommitteeManagementDebug(initialMembers, initialRequired, initialAuthorizedCallers, initialWatchtowers);
console.log("CommitteeManagement contract address: ", address(committeeManagement));

StakeManagement stakeManagement = new StakeManagement(IERC20(address(pegBTC)), address(gateway));
console.log("StakeManagement contract address: ", address(stakeManagement));
CommitteeManagementDebug committeeImpl = new CommitteeManagementDebug();
console.log(
"CommitteeManagement implementation contract address: ",
address(committeeImpl)
);
bytes memory committeeInitData = abi.encodeWithSelector(
CommitteeManagement.initialize.selector,
initialMembers,
initialRequired,
initialAuthorizedCallers,
initialWatchtowers
);
UpgradeableProxy committeeProxy = new UpgradeableProxy(
address(committeeImpl),
deployer,
committeeInitData
);
console.log(
"CommitteeManagement proxy contract address: ",
address(committeeProxy)
);
ICommitteeManagement committeeManagement = ICommitteeManagement(
address(committeeProxy)
);

StakeManagement stakeImpl = new StakeManagement();
console.log(
"StakeManagement implementation contract address: ",
address(stakeImpl)
);
bytes memory stakeInitData = abi.encodeWithSelector(
StakeManagement.initialize.selector,
IERC20(address(pegBTC)),
address(gateway)
);
UpgradeableProxy stakeProxy = new UpgradeableProxy(
address(stakeImpl),
deployer,
stakeInitData
);
console.log(
"StakeManagement proxy contract address: ",
address(stakeProxy)
);
IStakeManagement stakeManagement = IStakeManagement(
address(stakeProxy)
);

gateway.initialize(
IPegBTC(address(pegBTC)),
IBitcoinSPV(bitcoinSPV),
CommitteeManagement(address(committeeManagement)),
StakeManagement(address(stakeManagement))
committeeManagement,
stakeManagement
);
}

// Helpers: read env arrays as sequential variables with numeric suffixes
// Example: BASE=PREFIX, reads PREFIX_0, PREFIX_1, ... until a default is hit.
function _readSequentialAddresses(string memory baseKey) internal view returns (address[] memory out) {
// first pass: count
function _readSequentialAddresses(
string memory baseKey
) internal view returns (address[] memory out) {
uint256 count = 0;
while (true) {
string memory key = string(abi.encodePacked(baseKey, "_", vm.toString(count)));
string memory key = string(
abi.encodePacked(baseKey, "_", vm.toString(count))
);
address val = vm.envOr(key, address(0));
if (val == address(0)) break;
unchecked {
Expand All @@ -79,16 +137,21 @@ contract DeployGateway is Script {
}
out = new address[](count);
for (uint256 i = 0; i < count; i++) {
string memory key = string(abi.encodePacked(baseKey, "_", vm.toString(i)));
string memory key = string(
abi.encodePacked(baseKey, "_", vm.toString(i))
);
out[i] = vm.envAddress(key);
}
}

function _readSequentialBytes32(string memory baseKey) internal view returns (bytes32[] memory out) {
// first pass: count
function _readSequentialBytes32(
string memory baseKey
) internal view returns (bytes32[] memory out) {
uint256 count = 0;
while (true) {
string memory key = string(abi.encodePacked(baseKey, "_", vm.toString(count)));
string memory key = string(
abi.encodePacked(baseKey, "_", vm.toString(count))
);
bytes32 val = vm.envOr(key, bytes32(0));
if (val == bytes32(0)) break;
unchecked {
Expand All @@ -97,7 +160,9 @@ contract DeployGateway is Script {
}
out = new bytes32[](count);
for (uint256 i = 0; i < count; i++) {
string memory key = string(abi.encodePacked(baseKey, "_", vm.toString(i)));
string memory key = string(
abi.encodePacked(baseKey, "_", vm.toString(i))
);
out[i] = vm.envBytes32(key);
}
}
Expand Down
Loading