Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
2f10afe
feat: add verification scripts for proxy and implementation contracts
gfournierPro Jul 21, 2025
0ba9d73
feat: refactor verification targets to use reusable functions for pro…
gfournierPro Jul 21, 2025
27cf969
Merge branch 'main' into feature/re-add-verification-script
gfournierPro Jul 21, 2025
c36f051
feat: change folder from scripts/ to tools/
gfournierPro Jul 21, 2025
bec88aa
feat: simplify address extraction logic in get_config_address.sh
gfournierPro Jul 21, 2025
9cc00a4
feat: update constructor argument handling in verification scripts
gfournierPro Jul 21, 2025
2829f2d
feat: streamline implementation verification process in verification.mk
gfournierPro Jul 21, 2025
e6d06b1
feat: replace bash scripts with Solidity implementation for configura…
gfournierPro Jul 21, 2025
7158c40
feat: remove commented-out code for lzChainId in GetConfigInfo script
gfournierPro Jul 21, 2025
0410d89
feat: remove outdated comments and documentation from verification.mk
gfournierPro Jul 21, 2025
29d5af6
fix: forge fmt
gfournierPro Jul 22, 2025
c25f1c7
feat: update GetConfigInfo script to use config field names and impro…
gfournierPro Jul 22, 2025
61a0c49
fix: forge fmt
gfournierPro Jul 22, 2025
013ce86
feat: remove unused import of ConfigLib from GetConfigInfo script
gfournierPro Jul 22, 2025
e1d927e
fix: update GetConfigInfo script to retrieve rlcAddress instead of rl…
gfournierPro Jul 22, 2025
ec8391b
refactor: simplify GetConfigInfo script by removing chain parameter a…
gfournierPro Jul 22, 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: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MAKEFLAGS += --no-print-directory

include report.mk
include tools/report.mk tools/verification.mk
-include .env


Expand Down
33 changes: 33 additions & 0 deletions tools/get_config_address.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/bin/bash

# Script to extract contract addresses from config/config.json
# Usage: ./scripts/get_config_address.sh [chain] [field]

CONFIG_FILE="config/config.json"

if [ ! -f "$CONFIG_FILE" ]; then
echo "Error: config.json not found at $CONFIG_FILE"
exit 1
fi

if [ $# -lt 2 ]; then
echo "Usage: $0 [chain] [field]"
exit 1
fi

CHAIN=$1
FIELD=$2

# Extract the value using jq
VALUE=$(jq -r ".chains.${CHAIN}.${FIELD} // empty" "$CONFIG_FILE")
if [ -n "$VALUE" ] && [ "$VALUE" != "null" ]; then
echo "$VALUE"
exit 0
fi
GLOBAL_VALUE=$(jq -r ".global.${FIELD} // empty" "$CONFIG_FILE")
if [ -n "$GLOBAL_VALUE" ] && [ "$GLOBAL_VALUE" != "null" ]; then
echo "$GLOBAL_VALUE"
exit 0
fi
echo "Error: Field '${FIELD}' not found for chain '${CHAIN}'"
exit 1
38 changes: 38 additions & 0 deletions tools/get_implementation_address.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/bin/bash

# Script to get implementation address from a proxy contract
# Usage: ./scripts/get_implementation_address.sh [proxy_address] [rpc_url]

if [ $# -lt 2 ]; then
echo "Usage: $0 [proxy_address] [rpc_url]"
exit 1
fi

PROXY_ADDRESS=$1
RPC_URL=$2

# The ERC1967 implementation slot is at keccak256("eip1967.proxy.implementation") - 1
IMPL_SLOT="0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"

# Get the storage at the implementation slot
STORAGE_VALUE=$(cast storage "$PROXY_ADDRESS" "$IMPL_SLOT" --rpc-url "$RPC_URL" 2>/dev/null)

if [ $? -ne 0 ] || [ -z "$STORAGE_VALUE" ]; then
echo "Error: Failed to get storage from proxy contract" >&2
exit 1
fi

# Clean the storage value: remove warnings, whitespace, and extract the hex value
CLEAN_STORAGE=$(echo "$STORAGE_VALUE" | grep "^0x" | tr -d '\n\r' | tail -n1)

# Convert storage value to address (take last 40 hex chars and add 0x prefix)
IMPLEMENTATION_ADDRESS="0x$(echo "$CLEAN_STORAGE" | sed 's/^0x//' | tail -c 41)"

# Verify this is a valid contract
CODE=$(cast code "$IMPLEMENTATION_ADDRESS" --rpc-url "$RPC_URL" 2>/dev/null)
if [ -z "$CODE" ] || [ "$CODE" = "0x" ]; then
echo "Error: No code found at implementation address - this might not be a valid contract" >&2
exit 1
fi

echo "$IMPLEMENTATION_ADDRESS"
File renamed without changes.
127 changes: 127 additions & 0 deletions tools/verification.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@

# ========================================================================
# SMART CONTRACT VERIFICATION
# ========================================================================
# Chain IDs for supported networks
SEPOLIA_CHAIN_ID := 11155111
ARBITRUM_SEPOLIA_CHAIN_ID := 421614

# ========================================================================
# VERIFICATION FUNCTIONS
# ========================================================================

# Verify ERC1967 proxy contracts
# Parameters: CONTRACT_NAME, NETWORK, CONFIG_KEY, CHAIN_ID, DISPLAY_NAME
define verify-proxy
@echo "Verifying $(1) Proxy on $(5)..."
forge verify-contract \
--chain-id $(4) \
--watch \
--etherscan-api-key $(ETHERSCAN_API_KEY) \
$$(./tools/get_config_address.sh $(2) $(3)) \
lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy
@echo "Proxy verification completed for $(1) on $(5)"
endef

# Verify implementation contracts with optional constructor arguments
# Parameters: CONTRACT_NAME, NETWORK, CONFIG_KEY, CHAIN_ID, DISPLAY_NAME, CONTRACT_PATH, RPC_URL, CONSTRUCTOR_ARGS
define verify-impl
@echo "Verifying $(1) Implementation on $(5)..."
@proxy_address=$$(./tools/get_config_address.sh $(2) $(3)); \
impl_address=$$(./tools/get_implementation_address.sh $$proxy_address $(7) | tail -n 1); \
echo "Proxy address: $$proxy_address"; \
echo "Implementation address: $$impl_address"; \
forge verify-contract \
--chain-id $(4) \
--watch \
$(8) \
--etherscan-api-key $(ETHERSCAN_API_KEY) \
$$impl_address \
$(6); \
echo "Implementation verification completed for $(1) on $(5)"; \
echo ""
endef

# ========================================================================
# SEPOLIA NETWORK VERIFICATION
# ========================================================================

# Proxy Verifications - Sepolia
# -----------------------------
verify-rlc-liquidity-unifier-proxy-sepolia:
$(call verify-proxy,RLCLiquidityUnifier,sepolia,rlcLiquidityUnifierAddress,$(SEPOLIA_CHAIN_ID),Sepolia Etherscan)

verify-layerzero-bridge-proxy-sepolia:
$(call verify-proxy,IexecLayerZeroBridge,sepolia,iexecLayerZeroBridgeAddress,$(SEPOLIA_CHAIN_ID),Sepolia Etherscan)

# Implementation Verifications - Sepolia
# --------------------------------------
verify-rlc-liquidity-unifier-impl-sepolia:
@rlc_address=$$(./tools/get_config_address.sh sepolia rlcAddress); \
constructor_args=$$(cast abi-encode "constructor(address)" $$rlc_address); \
$(MAKE) _verify-rlc-liquidity-unifier-impl-sepolia CONSTRUCTOR_ARGS="--constructor-args $$constructor_args"

_verify-rlc-liquidity-unifier-impl-sepolia:
$(call verify-impl,RLCLiquidityUnifier,sepolia,rlcLiquidityUnifierAddress,$(SEPOLIA_CHAIN_ID),Sepolia Etherscan,src/RLCLiquidityUnifier.sol:RLCLiquidityUnifier,$(SEPOLIA_RPC_URL),$(CONSTRUCTOR_ARGS))

verify-layerzero-bridge-impl-sepolia:
@echo "Building constructor arguments for IexecLayerZeroBridge..."
@rlc_liquidity_unifier_address=$$(./tools/get_config_address.sh sepolia rlcLiquidityUnifierAddress); \
lz_endpoint_address=$$(./tools/get_config_address.sh sepolia lzEndpointAddress); \
constructor_args=$$(cast abi-encode "constructor(bool,address,address)" true $$rlc_liquidity_unifier_address $$lz_endpoint_address); \
$(MAKE) _verify-layerzero-bridge-impl-sepolia CONSTRUCTOR_ARGS="--constructor-args $$constructor_args"

_verify-layerzero-bridge-impl-sepolia:
$(call verify-impl,IexecLayerZeroBridge,sepolia,iexecLayerZeroBridgeAddress,$(SEPOLIA_CHAIN_ID),Sepolia Etherscan,src/bridges/layerZero/IexecLayerZeroBridge.sol:IexecLayerZeroBridge,$(SEPOLIA_RPC_URL),$(CONSTRUCTOR_ARGS))

# ========================================================================
# ARBITRUM SEPOLIA NETWORK VERIFICATION
# ========================================================================

# Proxy Verifications - Arbitrum Sepolia
# ---------------------------------------
verify-rlc-crosschain-token-proxy-arbitrum-sepolia:
$(call verify-proxy,RLCCrosschainToken,arbitrum_sepolia,rlcCrosschainTokenAddress,$(ARBITRUM_SEPOLIA_CHAIN_ID),Arbitrum Sepolia)

verify-layerzero-bridge-proxy-arbitrum-sepolia:
$(call verify-proxy,IexecLayerZeroBridge,arbitrum_sepolia,iexecLayerZeroBridgeAddress,$(ARBITRUM_SEPOLIA_CHAIN_ID),Arbitrum Sepolia)

# Implementation Verifications - Arbitrum Sepolia
# ------------------------------------------------
verify-rlc-crosschain-token-impl-arbitrum-sepolia:
$(call verify-impl,RLCCrosschainToken,arbitrum_sepolia,rlcCrosschainTokenAddress,$(ARBITRUM_SEPOLIA_CHAIN_ID),Arbitrum Sepolia,src/RLCCrosschainToken.sol:RLCCrosschainToken,$(ARBITRUM_SEPOLIA_RPC_URL),)

verify-layerzero-bridge-impl-arbitrum-sepolia:
@echo "🔧 Building constructor arguments for IexecLayerZeroBridge..."
@rlc_crosschain_token_address=$$(./tools/get_config_address.sh arbitrum_sepolia rlcCrosschainTokenAddress); \
lz_endpoint_address=$$(./tools/get_config_address.sh arbitrum_sepolia lzEndpointAddress); \
constructor_args=$$(cast abi-encode "constructor(bool,address,address)" false $$rlc_crosschain_token_address $$lz_endpoint_address); \
$(MAKE) _verify-layerzero-bridge-impl-arbitrum-sepolia CONSTRUCTOR_ARGS="--constructor-args $$constructor_args"

_verify-layerzero-bridge-impl-arbitrum-sepolia:
$(call verify-impl,IexecLayerZeroBridge,arbitrum_sepolia,iexecLayerZeroBridgeAddress,$(ARBITRUM_SEPOLIA_CHAIN_ID),Arbitrum Sepolia,src/bridges/layerZero/IexecLayerZeroBridge.sol:IexecLayerZeroBridge,$(ARBITRUM_SEPOLIA_RPC_URL),$(CONSTRUCTOR_ARGS))

# ========================================================================
# PROXY AND IMPLEMENTATION VERIFICATION
# ========================================================================
verify-proxies-sepolia: verify-rlc-liquidity-unifier-proxy-sepolia verify-layerzero-bridge-proxy-sepolia
verify-proxies-arbitrum-sepolia: verify-rlc-crosschain-token-proxy-arbitrum-sepolia verify-layerzero-bridge-proxy-arbitrum-sepolia
verify-proxies-testnets: verify-proxies-sepolia verify-proxies-arbitrum-sepolia

verify-implementations-sepolia: verify-rlc-liquidity-unifier-impl-sepolia verify-layerzero-bridge-impl-sepolia
verify-implementations-arbitrum-sepolia: verify-rlc-crosschain-token-impl-arbitrum-sepolia verify-layerzero-bridge-impl-arbitrum-sepolia
verify-implementations-testnets: verify-implementations-sepolia verify-implementations-arbitrum-sepolia


# ========================================================================
# COMPLETION TARGETS
Copy link

Copilot AI Jul 22, 2025

Choose a reason for hiding this comment

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

Inconsistent tab usage in comment formatting. This line uses tabs while other comment lines use spaces for alignment.

Suggested change
# COMPLETION TARGETS
# COMPLETION TARGETS

Copilot uses AI. Check for mistakes.
# ========================================================================

verify-all-sepolia: verify-proxies-sepolia verify-implementations-sepolia
verify-all-arbitrum-sepolia: verify-proxies-arbitrum-sepolia verify-implementations-arbitrum-sepolia
verify-all-testnets: verify-all-sepolia verify-all-arbitrum-sepolia


.PHONY: verify-all-testnets verify-all-sepolia verify-all-arbitrum-sepolia \
verify-proxies-sepolia verify-proxies-arbitrum-sepolia verify-proxies-testnets \
verify-implementations-sepolia verify-implementations-arbitrum-sepolia verify-implementations-testnets