Skip to content
Open
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
50 changes: 50 additions & 0 deletions contracts/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# -----------------------------------------------------------------------------
# LensMint Camera — Foundry deployment environment (example only)
# -----------------------------------------------------------------------------
# Copy this to `contracts/.env` (and DO NOT commit `contracts/.env`).
#
# IMPORTANT
# - Never put private keys directly into this file.
# - The signer for broadcasting is passed to `forge script` via CLI flags:
# --account <NAME> (Foundry/cast account name)
# OR --keystore <path> + --password-file <path>
# - This .env file is for public configuration like RPC URLs and verifier params.

# RPC URLs (used by deployMultichain.sh per network name)
SEPOLIA_RPC_URL="https://YOUR_SEPOLIA_RPC_URL"
MAINNET_RPC_URL="https://YOUR_MAINNET_RPC_URL"

# Optional networks (deployMultichain.sh will look for <NET>_RPC_URL)
ARBITRUM_RPC_URL="https://YOUR_ARBITRUM_RPC_URL"
POLYGON_RPC_URL="https://YOUR_POLYGON_RPC_URL"
BASE_RPC_URL="https://YOUR_BASE_RPC_URL"

# -----------------------------------------------------------------------------
# LensMintVerifier (only required if you deploy target "verifier")
# These are read by Solidity scripts via:
# vm.envString / vm.envBytes32 / vm.envOr
# -----------------------------------------------------------------------------
EXPECTED_URL="https://lensmint.onrender.com/api/metadata/" # must match the contract's expected URL pattern

# bytes32 values (0x... 32-byte hex)
ZK_PROVER_GUEST_ID="0x0000000000000000000000000000000000000000000000000000000000000000"
NOTARY_KEY_FINGERPRINT="0x0000000000000000000000000000000000000000000000000000000000000000"
QUERIES_HASH="0x000000000000000000000000000000000000000000000000000000000000000000"

# Optional: if set, DeployVerifier will reuse an existing RISC Zero verifier address
RISC_ZERO_VERIFIER_ADDRESS="0x0000000000000000000000000000000000000000"

# -----------------------------------------------------------------------------
# Etherscan verification (only if you pass --verify)
# -----------------------------------------------------------------------------
# Must match foundry.toml's [etherscan] section keys.
ETHERSCAN_API_KEY="YOUR_ETHERSCAN_API_KEY"

# -----------------------------------------------------------------------------
# Optional defaults for deployMultichain.sh (all can be overridden by CLI)
# -----------------------------------------------------------------------------
# NETWORKS="sepolia"
# DEPLOY_TARGETS="core"
# BROADCAST="true"
# VERIFY="false"

263 changes: 263 additions & 0 deletions contracts/deployMultichain.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
#!/usr/bin/env bash

set -euo pipefail

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Defaults (can be overridden by flags or env)
NETWORKS="${NETWORKS:-sepolia}"
TARGETS="${DEPLOY_TARGETS:-core}"
BROADCAST="${BROADCAST:-true}"
DO_VERIFY="${VERIFY:-false}"

# Signer (CLI)
ACCOUNT=""
KEYSTORE=""
PASSWORD=""
PASSWORD_FILE=""
PRIVATE_KEY_CLI=""

# Verifier params (flags override env)
FLAG_EXPECTED_URL=""
FLAG_ZK_PROVER_GUEST_ID=""
FLAG_NOTARY_KEY_FINGERPRINT=""
FLAG_QUERIES_HASH=""
FLAG_RISC_ZERO_VERIFIER=""

while [[ $# -gt 0 ]]; do
case $1 in
--networks)
NETWORKS="$2"
shift 2
;;
--targets)
TARGETS="$2"
shift 2
;;
--no-broadcast)
BROADCAST="false"
shift
;;
--broadcast)
BROADCAST="true"
shift
;;
--verify)
DO_VERIFY="true"
shift
;;
--account)
ACCOUNT="$2"
shift 2
;;
--keystore)
KEYSTORE="$2"
shift 2
;;
--password)
PASSWORD="$2"
shift 2
;;
--password-file)
PASSWORD_FILE="$2"
shift 2
;;
--private-key)
PRIVATE_KEY_CLI="$2"
shift 2
;;
--expected-url)
FLAG_EXPECTED_URL="$2"
shift 2
;;
--zk-prover-guest-id)
FLAG_ZK_PROVER_GUEST_ID="$2"
shift 2
;;
--notary-key-fingerprint)
FLAG_NOTARY_KEY_FINGERPRINT="$2"
shift 2
;;
--queries-hash)
FLAG_QUERIES_HASH="$2"
shift 2
;;
--risc-zero-verifier)
FLAG_RISC_ZERO_VERIFIER="$2"
shift 2
;;
--help|-h)
cat <<'EOF'
deployMultichain.sh — deploy LensMint contracts via forge script

USAGE
cd contracts && ./deployMultichain.sh [OPTIONS]

OPTIONS
--networks LIST Comma-separated names (default: sepolia). Examples: sepolia,mainnet
--targets LIST core | verifier | core,verifier (default: core)
--broadcast Send txs (default)
--no-broadcast Simulate only; no signer required
--verify Pass --verify to forge (needs ETHERSCAN_API_KEY)

SIGNER (required when broadcasting; same as forge script)
--account NAME
--keystore PATH [--password-file PATH | --password PASS]
--private-key HEX

VERIFIER CONFIG (if --targets includes verifier; or set env vars)
--expected-url URL
--zk-prover-guest-id 0x...
--notary-key-fingerprint 0x...
--queries-hash 0x...
--risc-zero-verifier ADDR Optional existing RISC Zero verifier address

ENVIRONMENT
SEPOLIA_RPC_URL, MAINNET_RPC_URL, ... For network name "foo", uses FOO_RPC_URL
EXPECTED_URL, ZK_PROVER_GUEST_ID, NOTARY_KEY_FINGERPRINT, QUERIES_HASH
RISC_ZERO_VERIFIER_ADDRESS (optional)
ETHERSCAN_API_KEY For --verify
NETWORKS, DEPLOY_TARGETS, BROADCAST, VERIFY Default overrides

CAST / WALLET SETUP (example)
cast wallet import deployer --interactive
./deployMultichain.sh --networks sepolia --account deployer

EFFECTIVE COMMAND (per script)
forge script <script> [--account|...] --rpc-url <url> --non-interactive -vvv [--broadcast] [--verify]
EOF
exit 0
;;
*)
echo -e "${RED}Unknown option: $1${NC}" >&2
exit 1
;;
esac
done

IFS=',' read -ra NETWORK_ARR <<< "$NETWORKS"
IFS=',' read -ra TARGETS_ARR <<< "$TARGETS"

has_target() {
local t="$1"
for x in "${TARGETS_ARR[@]}"; do
if [[ "$x" == "$t" ]]; then
return 0
fi
done
return 1
}

require_env() {
local v="$1"
if [[ -z "${!v:-}" ]]; then
echo -e "${RED}Missing required env var: $v${NC}" >&2
exit 1
fi
}

# Apply flag overrides into env for Solidity vm.env*()
export EXPECTED_URL="${FLAG_EXPECTED_URL:-${EXPECTED_URL:-}}"
export ZK_PROVER_GUEST_ID="${FLAG_ZK_PROVER_GUEST_ID:-${ZK_PROVER_GUEST_ID:-}}"
export NOTARY_KEY_FINGERPRINT="${FLAG_NOTARY_KEY_FINGERPRINT:-${NOTARY_KEY_FINGERPRINT:-}}"
export QUERIES_HASH="${FLAG_QUERIES_HASH:-${QUERIES_HASH:-}}"
if [[ -n "${FLAG_RISC_ZERO_VERIFIER:-}" ]]; then
export RISC_ZERO_VERIFIER_ADDRESS="$FLAG_RISC_ZERO_VERIFIER"
fi

SIGNER_ARGS=()
if [[ -n "$ACCOUNT" ]]; then SIGNER_ARGS+=(--account "$ACCOUNT"); fi
if [[ -n "$KEYSTORE" ]]; then SIGNER_ARGS+=(--keystore "$KEYSTORE"); fi
if [[ -n "$PASSWORD" ]]; then SIGNER_ARGS+=(--password "$PASSWORD"); fi
if [[ -n "$PASSWORD_FILE" ]]; then SIGNER_ARGS+=(--password-file "$PASSWORD_FILE"); fi
if [[ -n "$PRIVATE_KEY_CLI" ]]; then SIGNER_ARGS+=(--private-key "$PRIVATE_KEY_CLI"); fi

rpc_url_for() {
local net="$1"
local key="${net^^}_RPC_URL"
local v="${!key:-}"
if [[ -n "$v" ]]; then
echo "$v"
return 0
fi
echo -e "${YELLOW}Warning: $key not set; using --rpc-url \"$net\". Ensure Foundry rpc_endpoints resolve it.${NC}" >&2
echo "$net"
}

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$ROOT_DIR"

echo -e "${GREEN}Starting multichain deployment${NC}"
echo -e "${GREEN}Networks:${NC} ${NETWORKS}"
echo -e "${GREEN}Targets:${NC} ${TARGETS}"
echo -e "${GREEN}Broadcast mode:${NC} ${BROADCAST}"
echo -e "${GREEN}Etherscan verify:${NC} ${DO_VERIFY}"

if [[ "$BROADCAST" == "true" ]] && [[ ${#SIGNER_ARGS[@]} -eq 0 ]]; then
echo -e "${RED}Broadcasting requires a signer. Use one of:${NC}" >&2
echo -e " ${RED}--account <name> | --keystore <path> [--password-file <path>] | --private-key <hex>${NC}" >&2
echo -e "${YELLOW}Tip: cast wallet import mydeployer --interactive${NC}" >&2
exit 1
fi

if has_target "verifier"; then
require_env "EXPECTED_URL"
require_env "ZK_PROVER_GUEST_ID"
require_env "NOTARY_KEY_FINGERPRINT"
require_env "QUERIES_HASH"
fi

if [[ "$DO_VERIFY" == "true" ]]; then
if [[ -z "${ETHERSCAN_API_KEY:-}" ]]; then
echo -e "${YELLOW}Warning: ETHERSCAN_API_KEY is not set, --verify may fail.${NC}"
fi
fi

run_forge_script() {
local script_path="$1"
local rpc_url="$2"

local cmd=(forge script "$script_path")
if [[ ${#SIGNER_ARGS[@]} -gt 0 ]]; then
cmd+=("${SIGNER_ARGS[@]}")
fi
cmd+=(--rpc-url "$rpc_url" --non-interactive -vvv)
if [[ "$BROADCAST" == "true" ]]; then
cmd+=(--broadcast)
fi
if [[ "$DO_VERIFY" == "true" ]]; then
cmd+=(--verify)
fi

echo -e "\n${GREEN}========================================${NC}"
echo -e "${GREEN}Running:${NC} $script_path"
echo -e "${GREEN}RPC:${NC} $rpc_url"
echo -e "${GREEN}Broadcast:${NC} $BROADCAST"
echo -e "${GREEN}========================================${NC}\n"

"${cmd[@]}"
}

for net in "${NETWORK_ARR[@]}"; do
echo ""
echo -e "${GREEN}=== Deploying to: ${net}${NC} ==="
export NETWORK="$net"
rpc_url="$(rpc_url_for "$net")"

if has_target "core"; then
echo -e "${YELLOW}[core] Deploy DeviceRegistry + LensMintERC1155${NC}"
run_forge_script "script/Deploy.s.sol" "$rpc_url"
fi

if has_target "verifier"; then
echo -e "${YELLOW}[verifier] Deploy LensMintVerifier (zk verifier wrapper)${NC}"
run_forge_script "script/DeployVerifier.s.sol" "$rpc_url"
fi
done

echo ""
echo -e "${GREEN}Multichain deployment finished.${NC}"
5 changes: 2 additions & 3 deletions contracts/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ solc_version = "0.8.31"
optimizer = true
optimizer_runs = 200
via_ir = true
evm_version = "paris"
evm_version = "cancun"

[profile.ci]
fuzz = { runs = 100 }
Expand All @@ -19,5 +19,4 @@ sepolia = "${SEPOLIA_RPC_URL}"
mainnet = "${MAINNET_RPC_URL}"

[etherscan]
sepolia = { key = "${ETHERSCAN_API_KEY}" }

sepolia = { key = "${ETHERSCAN_API_KEY}" }
15 changes: 4 additions & 11 deletions contracts/script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,19 @@ import {LensMintERC1155} from "../src/LensMintERC1155.sol";

contract DeployScript is Script {
function run() external {
// Load deployer private key from environment
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
address deployer = vm.addr(deployerPrivateKey);

// Signer must be supplied via forge CLI (--account, --keystore, --password, --private-key, etc.)
console.log("Deploying contracts...");
console.log("Deployer address:", deployer);
console.log("Deployer balance:", deployer.balance);
console.log("Signer: forge broadcast (see forge script --help)");

vm.startBroadcast(deployerPrivateKey);
vm.startBroadcast();

console.log("\nDeploying DeviceRegistry...");
DeviceRegistry deviceRegistry = new DeviceRegistry();
console.log("DeviceRegistry deployed at:", address(deviceRegistry));

console.log("\nDeploying LensMintERC1155...");
string memory baseURI = "https://ipfs.io/ipfs/";
LensMintERC1155 lensMint = new LensMintERC1155(
address(deviceRegistry),
baseURI
);
LensMintERC1155 lensMint = new LensMintERC1155(address(deviceRegistry), baseURI);
console.log("LensMintERC1155 deployed at:", address(lensMint));

vm.stopBroadcast();
Expand Down
Loading