181 lines
7.0 KiB
Bash
Executable File
181 lines
7.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Export BSC cW* verification artifacts: pinned profile build + Standard JSON for BscScan manual upload.
|
|
#
|
|
# Usage (from smom-dbis-138/):
|
|
# ./scripts/deployment/export-bsc-cw-verification-artifacts.sh
|
|
# ./scripts/deployment/export-bsc-cw-verification-artifacts.sh --verify # also submit forge verify (cWBNB may fail)
|
|
#
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
REPO_ROOT="$(cd "$PROJECT_ROOT/.." && pwd)"
|
|
OUT_DIR="$REPO_ROOT/reports/status/bsc-cw-verification"
|
|
VERIFY=0
|
|
[[ "${1:-}" == "--verify" ]] && VERIFY=1
|
|
|
|
cd "$PROJECT_ROOT"
|
|
|
|
if [[ -f "$SCRIPT_DIR/../lib/deployment/dotenv.sh" ]]; then
|
|
# shellcheck disable=SC1090
|
|
source "$SCRIPT_DIR/../lib/deployment/dotenv.sh"
|
|
load_deployment_env --repo-root "$PROJECT_ROOT"
|
|
fi
|
|
|
|
[[ -n "${ETHERSCAN_API_KEY:-}" ]] || { echo "ETHERSCAN_API_KEY required" >&2; exit 1; }
|
|
|
|
ADMIN="${CW_VERIFY_ADMIN:-}"
|
|
if [[ -z "$ADMIN" && -n "${PRIVATE_KEY:-}" ]]; then
|
|
ADMIN="$(cast wallet address --private-key "$PRIVATE_KEY")"
|
|
fi
|
|
[[ -n "$ADMIN" ]] || { echo "CW_VERIFY_ADMIN or PRIVATE_KEY required" >&2; exit 1; }
|
|
|
|
CWBNB="${CWBNB_BSC:-0x179034a08ac2c9c35d2e41239f68c79dca6f18fa}"
|
|
CONTRACT_PATH="contracts/tokens/CompliantWrappedToken.sol:CompliantWrappedToken"
|
|
CTOR="$(cast abi-encode 'constructor(string,string,uint8,address)' \
|
|
'Wrapped BNB Gas (Compliant)' 'cWBNB' 18 "$ADMIN")"
|
|
|
|
mkdir -p "$OUT_DIR"
|
|
|
|
echo "==> Pinned profile: bsc_tokens_verify (see foundry.toml + config/bsc-cw-verify-profile.v1.json)"
|
|
echo "==> Scoped build: scripts/forge/scope.sh build tokens"
|
|
export FOUNDRY_PROFILE=bsc_tokens_verify
|
|
export FOUNDRY_SRC="contracts/tokens,contracts/interfaces"
|
|
export FOUNDRY_OUT="out/scopes/tokens"
|
|
export FOUNDRY_CACHE_PATH="cache/scopes/tokens"
|
|
bash "$PROJECT_ROOT/scripts/forge/scope.sh" build tokens
|
|
|
|
echo "==> Export Standard JSON Input (upload at https://bscscan.com/verifyContract solidity-standard-json-input)"
|
|
JSON_OUT="$OUT_DIR/CompliantWrappedToken_cWBNB_standard_input.json"
|
|
# forge may print ERROR log lines before the JSON object on stdout — keep only the JSON line
|
|
forge verify-contract \
|
|
--chain bsc \
|
|
--num-of-optimizations 200 \
|
|
--via-ir \
|
|
--evm-version london \
|
|
--compiler-version "0.8.20+commit.a1b79de6" \
|
|
--constructor-args "$CTOR" \
|
|
--show-standard-json-input \
|
|
"$CWBNB" \
|
|
"$CONTRACT_PATH" 2>/dev/null | awk '/^\{/{buf=$0} END{if(buf) print buf}' | jq -c . > "$JSON_OUT"
|
|
[[ -s "$JSON_OUT" ]] || { echo "Failed to write Standard JSON (forge output empty?)" >&2; exit 5; }
|
|
echo " wrote $JSON_OUT"
|
|
|
|
echo "==> Export flattened source (reference only; prefer Standard-JSON for via-ir)"
|
|
forge flatten contracts/tokens/CompliantWrappedToken.sol > "$OUT_DIR/CompliantWrappedToken_cWBNB_flattened.sol" 2>/dev/null
|
|
echo " wrote $OUT_DIR/CompliantWrappedToken_cWBNB_flattened.sol"
|
|
|
|
RPC="${BSC_RPC_URL:-${BSC_MAINNET_RPC:-}}"
|
|
if [[ -n "$RPC" ]]; then
|
|
ONCHAIN="$(cast code "$CWBNB" --rpc-url "$RPC" | sed 's/^0x//' | tr '[:upper:]' '[:lower:]')"
|
|
BUILT="$(jq -r .deployedBytecode.object "$FOUNDRY_OUT/CompliantWrappedToken.sol/CompliantWrappedToken.json" | sed 's/^0x//' | tr '[:upper:]' '[:lower:]')"
|
|
MATCH=false
|
|
[[ "$ONCHAIN" == "$BUILT" ]] && MATCH=true
|
|
FIRST_DIFF_OFFSET=""
|
|
if [[ "$MATCH" == false ]]; then
|
|
FIRST_DIFF_OFFSET="$(python3 -c "
|
|
on, b = '''$ONCHAIN''', '''$BUILT'''
|
|
n = min(len(on), len(b)) // 2
|
|
for i in range(n):
|
|
if on[2*i:2*i+2] != b[2*i:2*i+2]:
|
|
print(i)
|
|
break
|
|
else:
|
|
print(n if len(on)//2 != len(b)//2 else '')
|
|
" 2>/dev/null || true)"
|
|
fi
|
|
jq -n \
|
|
--arg generatedAt "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
--arg address "$CWBNB" \
|
|
--argjson onChainRuntimeBytes $(( ${#ONCHAIN} / 2 )) \
|
|
--argjson pinnedBuildRuntimeBytes $(( ${#BUILT} / 2 )) \
|
|
--argjson runtimeBytecodeMatch "$([[ "$MATCH" == true ]] && echo true || echo false)" \
|
|
--arg firstRuntimeDiffOffset "${FIRST_DIFF_OFFSET:-null}" \
|
|
--arg constructorArgs "$CTOR" \
|
|
--arg foundryProfile "bsc_tokens_verify" \
|
|
--arg standardJson "$JSON_OUT" \
|
|
'{
|
|
generatedAt: $generatedAt,
|
|
address: $address,
|
|
onChainRuntimeBytes: $onChainRuntimeBytes,
|
|
pinnedBuildRuntimeBytes: $pinnedBuildRuntimeBytes,
|
|
runtimeBytecodeMatch: $runtimeBytecodeMatch,
|
|
firstRuntimeDiffOffset: (if $firstRuntimeDiffOffset == "" or $firstRuntimeDiffOffset == "null" then null else ($firstRuntimeDiffOffset|tonumber) end),
|
|
constructorArgs: $constructorArgs,
|
|
foundryProfile: $foundryProfile,
|
|
standardJson: $standardJson
|
|
}' > "$OUT_DIR/cWBNB_bytecode_compare.json"
|
|
echo " wrote $OUT_DIR/cWBNB_bytecode_compare.json"
|
|
fi
|
|
|
|
cat > "$OUT_DIR/README.md" <<EOF
|
|
# BSC cWBNB verification artifacts
|
|
|
|
Generated by \`smom-dbis-138/scripts/deployment/export-bsc-cw-verification-artifacts.sh\`.
|
|
|
|
## Pinned compiler (matches verified BSC cWUSDT)
|
|
|
|
| Setting | Value |
|
|
|---------|--------|
|
|
| Profile | \`bsc_tokens_verify\` in \`foundry.toml\` |
|
|
| solc | \`0.8.20+commit.a1b79de6\` |
|
|
| Optimizer | enabled, **200** runs |
|
|
| via-ir | **true** (required — stack too deep without) |
|
|
| EVM | **london** (not cancun) |
|
|
| Scope | \`FOUNDRY_SRC=contracts/tokens,contracts/interfaces\`, \`FOUNDRY_OUT=out/scopes/tokens\` |
|
|
|
|
## Manual BscScan steps
|
|
|
|
1. Open https://bscscan.com/verifyContract
|
|
2. Contract address: \`$CWBNB\`
|
|
3. Compiler type: **Solidity (Standard-Json-Input)**
|
|
4. Upload \`CompliantWrappedToken_cWBNB_standard_input.json\`
|
|
5. Constructor arguments ABI-encoded (hex): see \`cWBNB_bytecode_compare.json\` or run:
|
|
|
|
\`\`\`bash
|
|
cast abi-encode 'constructor(string,string,uint8,address)' 'Wrapped BNB Gas (Compliant)' 'cWBNB' 18 <ADMIN>
|
|
\`\`\`
|
|
|
|
## If verification still fails
|
|
|
|
On-chain runtime bytecode is **~45 bytes longer** than the current pinned scoped build (see \`cWBNB_bytecode_compare.json\`). That indicates deploy used a slightly different artifact (solc patch, source revision, or metadata), not just constructor naming. Options:
|
|
|
|
- Locate the deploy transaction and pin the exact \`solc\` commit from that date.
|
|
- Compare \`git log contracts/tokens/CompliantWrappedToken.sol\` at deploy block.
|
|
- Redeploy cWBNB only if a new address is acceptable.
|
|
|
|
## Automated verify (may fail until bytecode pin found)
|
|
|
|
\`\`\`bash
|
|
cd smom-dbis-138
|
|
FOUNDRY_PROFILE=bsc_tokens_verify \\
|
|
FOUNDRY_SRC=contracts/tokens FOUNDRY_OUT=out/scopes/tokens \\
|
|
forge verify-contract --chain bsc --num-of-optimizations 200 --via-ir --evm-version london \\
|
|
--compiler-version 0.8.20+commit.a1b79de6 \\
|
|
--etherscan-api-key "\$ETHERSCAN_API_KEY" \\
|
|
--constructor-args "\$CTOR" \\
|
|
$CWBNB $CONTRACT_PATH
|
|
\`\`\`
|
|
EOF
|
|
echo " wrote $OUT_DIR/README.md"
|
|
|
|
if [[ "$VERIFY" -eq 1 ]]; then
|
|
echo "==> forge verify-contract (automated)"
|
|
set +e
|
|
forge verify-contract \
|
|
--chain bsc \
|
|
--num-of-optimizations 200 \
|
|
--via-ir \
|
|
--evm-version london \
|
|
--compiler-version "0.8.20+commit.a1b79de6" \
|
|
--etherscan-api-key "${ETHERSCAN_API_KEY}" \
|
|
--constructor-args "$CTOR" \
|
|
--watch --rpc-timeout 120 \
|
|
"$CWBNB" \
|
|
"$CONTRACT_PATH"
|
|
set -e
|
|
fi
|
|
|
|
echo ""
|
|
echo "Done. Artifacts: $OUT_DIR/"
|