From f5e96e7249cc66e9381d85b9aafdcc54e8a1c24f Mon Sep 17 00:00:00 2001 From: Derek Cofausper <256792747+decofe@users.noreply.github.com> Date: Fri, 3 Apr 2026 17:46:58 +0000 Subject: [PATCH 01/12] docs: specify symmetric deposit bounceback mechanism Recreates #329 which was closed due to force push on main. Rebased on current main branch. Co-Authored-By: dankrad <6130607+dankrad@users.noreply.github.com> Amp-Thread-ID: https://ampcode.com/threads/T-019d5473-3933-756c-8b65-60dfe41cb262 --- .amp/tools/tempo-bench | 66 ++ .amp/tools/tempo-infra | 31 + .amp/tools/tempo-kill | 15 + .amp/tools/tempo-localnet | 60 ++ .mergify.yml | 8 + Cargo.lock | 26 +- Cargo.toml | 24 +- Justfile | 4 +- crates/precompiles/src/ztip20.rs | 66 +- crates/primitives/src/abi.rs | 17 +- crates/rpc/Cargo.toml | 2 +- crates/rpc/src/auth/token.rs | 48 +- crates/rpc/src/config.rs | 2 +- crates/rpc/src/error.rs | 4 +- crates/rpc/src/provider.rs | 16 +- crates/rpc/src/server.rs | 4 +- crates/rpc/tests/it/ws.rs | 15 +- crates/tempo-zone/Cargo.toml | 2 +- crates/tempo-zone/src/builder.rs | 4 +- crates/tempo-zone/src/l1.rs | 40 +- crates/tempo-zone/tests/advance_tempo.rs | 3 +- crates/tempo-zone/tests/it/private_rpc.rs | 88 ++- crates/tempo-zone/tests/it/private_rpc_e2e.rs | 7 +- crates/tempo-zone/tests/it/utils.rs | 70 +- docs/pages/protocol/privacy/overview.md | 169 ++++- docs/pages/protocol/privacy/rpc.md | 22 +- docs/specs/src/zone/IZone.sol | 38 +- docs/specs/src/zone/SwapAndDepositRouter.sol | 5 +- docs/specs/src/zone/ZoneInbox.sol | 81 ++- docs/specs/src/zone/ZoneOutbox.sol | 30 + docs/specs/src/zone/ZonePortal.sol | 54 +- docs/specs/test/zone/DepositQueueLib.t.sol | 52 +- .../test/zone/SwapAndDepositRouter.t.sol | 6 +- docs/specs/test/zone/ZoneBridge.t.sol | 77 ++- docs/specs/test/zone/ZoneInbox.t.sol | 97 ++- docs/specs/test/zone/ZoneIntegration.t.sol | 86 ++- docs/specs/test/zone/ZoneOutbox.t.sol | 2 +- docs/specs/test/zone/ZonePortal.t.sol | 129 ++-- tempo.nu | 629 ++++++++++++++++++ 39 files changed, 1688 insertions(+), 411 deletions(-) create mode 100755 .amp/tools/tempo-bench create mode 100755 .amp/tools/tempo-infra create mode 100755 .amp/tools/tempo-kill create mode 100755 .amp/tools/tempo-localnet create mode 100644 .mergify.yml create mode 100755 tempo.nu diff --git a/.amp/tools/tempo-bench b/.amp/tools/tempo-bench new file mode 100755 index 000000000..3cb0a52b7 --- /dev/null +++ b/.amp/tools/tempo-bench @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +# Amp toolbox tool: Run a full Tempo benchmark + +if [ "$TOOLBOX_ACTION" = "describe" ]; then + cat <<'EOF' +name: tempo-bench +description: Run a full Tempo benchmark with observability stack, nodes, and tempo-bench. Use this instead of manually running nu tempo.nu bench. +preset: string Transaction type preset: tip20, erc20, swap, order, or tempo-mix (required unless bench_args provided) +mode: string Mode: dev or consensus (default: consensus) +tps: number Target transactions per second (default: 10000) +duration: number Duration in seconds (default: 30) +accounts: number Number of accounts (default: 1000) +nodes: number Number of consensus nodes (default: 3, consensus mode only) +genesis: string Custom genesis file path (skips generation) +reset: boolean Reset localnet before starting (default: false) +loud: boolean Show all node logs (default: false, only WARN/ERROR shown) +samply: boolean Profile nodes with samply (default: false) +samply_args: string Additional samply arguments (space-separated) +profile: string Cargo build profile (default: profiling) +features: string Cargo features (default: jemalloc,asm-keccak) +node_args: string Additional node arguments (space-separated) +bench_args: string Additional tempo-bench arguments (space-separated) +EOF + exit 0 +fi + +if [ "$TOOLBOX_ACTION" = "execute" ]; then + input=$(cat) + + preset=$(echo "$input" | grep -E '^preset:' | sed 's/^preset: *//') + mode=$(echo "$input" | grep -E '^mode:' | sed 's/^mode: *//') + tps=$(echo "$input" | grep -E '^tps:' | sed 's/^tps: *//') + duration=$(echo "$input" | grep -E '^duration:' | sed 's/^duration: *//') + accounts=$(echo "$input" | grep -E '^accounts:' | sed 's/^accounts: *//') + nodes=$(echo "$input" | grep -E '^nodes:' | sed 's/^nodes: *//') + genesis=$(echo "$input" | grep -E '^genesis:' | sed 's/^genesis: *//') + reset=$(echo "$input" | grep -E '^reset:' | sed 's/^reset: *//') + loud=$(echo "$input" | grep -E '^loud:' | sed 's/^loud: *//') + samply=$(echo "$input" | grep -E '^samply:' | sed 's/^samply: *//') + samply_args=$(echo "$input" | grep -E '^samply_args:' | sed 's/^samply_args: *//') + profile=$(echo "$input" | grep -E '^profile:' | sed 's/^profile: *//') + features=$(echo "$input" | grep -E '^features:' | sed 's/^features: *//') + node_args=$(echo "$input" | grep -E '^node_args:' | sed 's/^node_args: *//') + bench_args=$(echo "$input" | grep -E '^bench_args:' | sed 's/^bench_args: *//') + + cmd="nu tempo.nu bench" + + [ -n "$preset" ] && cmd="$cmd --preset $preset" + [ -n "$mode" ] && cmd="$cmd --mode $mode" + [ -n "$tps" ] && cmd="$cmd --tps $tps" + [ -n "$duration" ] && cmd="$cmd --duration $duration" + [ -n "$accounts" ] && cmd="$cmd --accounts $accounts" + [ -n "$nodes" ] && cmd="$cmd --nodes $nodes" + [ -n "$genesis" ] && cmd="$cmd --genesis $genesis" + [ "$reset" = "true" ] && cmd="$cmd --reset" + [ "$loud" = "true" ] && cmd="$cmd --loud" + [ "$samply" = "true" ] && cmd="$cmd --samply" + [ -n "$samply_args" ] && cmd="$cmd --samply-args=\"$samply_args\"" + [ -n "$profile" ] && cmd="$cmd --profile $profile" + [ -n "$features" ] && cmd="$cmd --features $features" + [ -n "$node_args" ] && cmd="$cmd --node-args=\"$node_args\"" + [ -n "$bench_args" ] && cmd="$cmd --bench-args=\"$bench_args\"" + + echo "Running: $cmd" + eval "$cmd" +fi diff --git a/.amp/tools/tempo-infra b/.amp/tools/tempo-infra new file mode 100755 index 000000000..36d218a3d --- /dev/null +++ b/.amp/tools/tempo-infra @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# Amp toolbox tool: Manage the observability stack (Grafana + Prometheus) + +if [ "$TOOLBOX_ACTION" = "describe" ]; then + cat <<'EOF' +name: tempo-infra +description: Start or stop the observability stack (Grafana + Prometheus) for benchmarking. Use this instead of manually running nu tempo.nu infra up/down. +action: string Action to perform: up or down (required) +EOF + exit 0 +fi + +if [ "$TOOLBOX_ACTION" = "execute" ]; then + input=$(cat) + + action=$(echo "$input" | grep -E '^action:' | sed 's/^action: *//') + + if [ -z "$action" ]; then + echo "Error: action is required (up or down)" + exit 1 + fi + + if [ "$action" != "up" ] && [ "$action" != "down" ]; then + echo "Error: action must be 'up' or 'down'" + exit 1 + fi + + cmd="nu tempo.nu infra $action" + echo "Running: $cmd" + eval "$cmd" +fi diff --git a/.amp/tools/tempo-kill b/.amp/tools/tempo-kill new file mode 100755 index 000000000..efb67cb73 --- /dev/null +++ b/.amp/tools/tempo-kill @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# Amp toolbox tool: Kill running tempo processes and cleanup + +if [ "$TOOLBOX_ACTION" = "describe" ]; then + cat <<'EOF' +name: tempo-kill +description: Kill any running tempo processes and cleanup stale IPC sockets. Use this instead of manually running nu tempo.nu kill. +EOF + exit 0 +fi + +if [ "$TOOLBOX_ACTION" = "execute" ]; then + echo "Running: nu tempo.nu kill" + nu tempo.nu kill +fi diff --git a/.amp/tools/tempo-localnet b/.amp/tools/tempo-localnet new file mode 100755 index 000000000..428ced9dd --- /dev/null +++ b/.amp/tools/tempo-localnet @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +# Amp toolbox tool: Run Tempo node(s) for benchmarking + +if [ "$TOOLBOX_ACTION" = "describe" ]; then + cat <<'EOF' +name: tempo-localnet +description: Run Tempo node(s) for benchmarking. Supports dev mode (single node) or consensus mode (multiple validators). Use this instead of manually running nu tempo.nu localnet. +mode: string Mode: dev or consensus (default: dev) +nodes: number Number of validators for consensus mode (default: 3) +accounts: number Number of genesis accounts (default: 1000) +genesis: string Custom genesis file path (skips generation) +reset: boolean Wipe and regenerate localnet data (default: false) +loud: boolean Show all node logs (default: false, only WARN/ERROR shown) +samply: boolean Enable samply profiling for foreground node (default: false) +samply_args: string Additional samply arguments (space-separated) +profile: string Cargo build profile (default: profiling) +features: string Cargo features (default: jemalloc,asm-keccak) +node_args: string Additional node arguments (space-separated) +skip_build: boolean Skip building the binary (default: false) +force: boolean Kill dangling processes without prompting (default: false) +EOF + exit 0 +fi + +if [ "$TOOLBOX_ACTION" = "execute" ]; then + input=$(cat) + + mode=$(echo "$input" | grep -E '^mode:' | sed 's/^mode: *//') + nodes=$(echo "$input" | grep -E '^nodes:' | sed 's/^nodes: *//') + accounts=$(echo "$input" | grep -E '^accounts:' | sed 's/^accounts: *//') + genesis=$(echo "$input" | grep -E '^genesis:' | sed 's/^genesis: *//') + reset=$(echo "$input" | grep -E '^reset:' | sed 's/^reset: *//') + loud=$(echo "$input" | grep -E '^loud:' | sed 's/^loud: *//') + samply=$(echo "$input" | grep -E '^samply:' | sed 's/^samply: *//') + samply_args=$(echo "$input" | grep -E '^samply_args:' | sed 's/^samply_args: *//') + profile=$(echo "$input" | grep -E '^profile:' | sed 's/^profile: *//') + features=$(echo "$input" | grep -E '^features:' | sed 's/^features: *//') + node_args=$(echo "$input" | grep -E '^node_args:' | sed 's/^node_args: *//') + skip_build=$(echo "$input" | grep -E '^skip_build:' | sed 's/^skip_build: *//') + force=$(echo "$input" | grep -E '^force:' | sed 's/^force: *//') + + cmd="nu tempo.nu localnet" + + [ -n "$mode" ] && cmd="$cmd --mode $mode" + [ -n "$nodes" ] && cmd="$cmd --nodes $nodes" + [ -n "$accounts" ] && cmd="$cmd --accounts $accounts" + [ -n "$genesis" ] && cmd="$cmd --genesis $genesis" + [ "$reset" = "true" ] && cmd="$cmd --reset" + [ "$loud" = "true" ] && cmd="$cmd --loud" + [ "$samply" = "true" ] && cmd="$cmd --samply" + [ -n "$samply_args" ] && cmd="$cmd --samply-args=\"$samply_args\"" + [ -n "$profile" ] && cmd="$cmd --profile $profile" + [ -n "$features" ] && cmd="$cmd --features $features" + [ -n "$node_args" ] && cmd="$cmd --node-args=\"$node_args\"" + [ "$skip_build" = "true" ] && cmd="$cmd --skip-build" + [ "$force" = "true" ] && cmd="$cmd --force" + + echo "Running: $cmd" + eval "$cmd" +fi diff --git a/.mergify.yml b/.mergify.yml new file mode 100644 index 000000000..339920c94 --- /dev/null +++ b/.mergify.yml @@ -0,0 +1,8 @@ +pull_request_rules: + - name: add "S-breaking-stf" label when the title contains "!" + conditions: + - title ~= ^.*!(.*).* + actions: + label: + toggle: + - S-breaking-stf diff --git a/Cargo.lock b/Cargo.lock index c60ffdb39..2d83daa04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10478,7 +10478,7 @@ dependencies = [ [[package]] name = "tempo-alloy" version = "1.5.0" -source = "git+https://github.com/tempoxyz/tempo?rev=e331e2f488a368ea9ca76c422e12fedbfb6eb3b4#e331e2f488a368ea9ca76c422e12fedbfb6eb3b4" +source = "git+https://github.com/tempoxyz/tempo?rev=698f7cb1b3d057cf67bbd81b21af53dfeb231610#698f7cb1b3d057cf67bbd81b21af53dfeb231610" dependencies = [ "alloy-consensus", "alloy-contract", @@ -10510,7 +10510,7 @@ dependencies = [ [[package]] name = "tempo-chainspec" version = "1.5.0" -source = "git+https://github.com/tempoxyz/tempo?rev=e331e2f488a368ea9ca76c422e12fedbfb6eb3b4#e331e2f488a368ea9ca76c422e12fedbfb6eb3b4" +source = "git+https://github.com/tempoxyz/tempo?rev=698f7cb1b3d057cf67bbd81b21af53dfeb231610#698f7cb1b3d057cf67bbd81b21af53dfeb231610" dependencies = [ "alloy-eips", "alloy-evm", @@ -10531,7 +10531,7 @@ dependencies = [ [[package]] name = "tempo-consensus" version = "1.5.0" -source = "git+https://github.com/tempoxyz/tempo?rev=e331e2f488a368ea9ca76c422e12fedbfb6eb3b4#e331e2f488a368ea9ca76c422e12fedbfb6eb3b4" +source = "git+https://github.com/tempoxyz/tempo?rev=698f7cb1b3d057cf67bbd81b21af53dfeb231610#698f7cb1b3d057cf67bbd81b21af53dfeb231610" dependencies = [ "alloy-consensus", "alloy-evm", @@ -10547,7 +10547,7 @@ dependencies = [ [[package]] name = "tempo-contracts" version = "1.5.0" -source = "git+https://github.com/tempoxyz/tempo?rev=e331e2f488a368ea9ca76c422e12fedbfb6eb3b4#e331e2f488a368ea9ca76c422e12fedbfb6eb3b4" +source = "git+https://github.com/tempoxyz/tempo?rev=698f7cb1b3d057cf67bbd81b21af53dfeb231610#698f7cb1b3d057cf67bbd81b21af53dfeb231610" dependencies = [ "alloy-contract", "alloy-primitives", @@ -10558,7 +10558,7 @@ dependencies = [ [[package]] name = "tempo-evm" version = "1.5.0" -source = "git+https://github.com/tempoxyz/tempo?rev=e331e2f488a368ea9ca76c422e12fedbfb6eb3b4#e331e2f488a368ea9ca76c422e12fedbfb6eb3b4" +source = "git+https://github.com/tempoxyz/tempo?rev=698f7cb1b3d057cf67bbd81b21af53dfeb231610#698f7cb1b3d057cf67bbd81b21af53dfeb231610" dependencies = [ "alloy-consensus", "alloy-evm", @@ -10588,7 +10588,7 @@ dependencies = [ [[package]] name = "tempo-node" version = "1.5.0" -source = "git+https://github.com/tempoxyz/tempo?rev=e331e2f488a368ea9ca76c422e12fedbfb6eb3b4#e331e2f488a368ea9ca76c422e12fedbfb6eb3b4" +source = "git+https://github.com/tempoxyz/tempo?rev=698f7cb1b3d057cf67bbd81b21af53dfeb231610#698f7cb1b3d057cf67bbd81b21af53dfeb231610" dependencies = [ "alloy", "alloy-eips", @@ -10639,7 +10639,7 @@ dependencies = [ [[package]] name = "tempo-payload-builder" version = "1.5.0" -source = "git+https://github.com/tempoxyz/tempo?rev=e331e2f488a368ea9ca76c422e12fedbfb6eb3b4#e331e2f488a368ea9ca76c422e12fedbfb6eb3b4" +source = "git+https://github.com/tempoxyz/tempo?rev=698f7cb1b3d057cf67bbd81b21af53dfeb231610#698f7cb1b3d057cf67bbd81b21af53dfeb231610" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -10673,7 +10673,7 @@ dependencies = [ [[package]] name = "tempo-payload-types" version = "1.5.0" -source = "git+https://github.com/tempoxyz/tempo?rev=e331e2f488a368ea9ca76c422e12fedbfb6eb3b4#e331e2f488a368ea9ca76c422e12fedbfb6eb3b4" +source = "git+https://github.com/tempoxyz/tempo?rev=698f7cb1b3d057cf67bbd81b21af53dfeb231610#698f7cb1b3d057cf67bbd81b21af53dfeb231610" dependencies = [ "alloy-eips", "alloy-primitives", @@ -10691,7 +10691,7 @@ dependencies = [ [[package]] name = "tempo-precompiles" version = "1.5.0" -source = "git+https://github.com/tempoxyz/tempo?rev=e331e2f488a368ea9ca76c422e12fedbfb6eb3b4#e331e2f488a368ea9ca76c422e12fedbfb6eb3b4" +source = "git+https://github.com/tempoxyz/tempo?rev=698f7cb1b3d057cf67bbd81b21af53dfeb231610#698f7cb1b3d057cf67bbd81b21af53dfeb231610" dependencies = [ "alloy", "alloy-evm", @@ -10710,7 +10710,7 @@ dependencies = [ [[package]] name = "tempo-precompiles-macros" version = "1.5.0" -source = "git+https://github.com/tempoxyz/tempo?rev=e331e2f488a368ea9ca76c422e12fedbfb6eb3b4#e331e2f488a368ea9ca76c422e12fedbfb6eb3b4" +source = "git+https://github.com/tempoxyz/tempo?rev=698f7cb1b3d057cf67bbd81b21af53dfeb231610#698f7cb1b3d057cf67bbd81b21af53dfeb231610" dependencies = [ "alloy", "proc-macro2", @@ -10721,7 +10721,7 @@ dependencies = [ [[package]] name = "tempo-primitives" version = "1.5.0" -source = "git+https://github.com/tempoxyz/tempo?rev=e331e2f488a368ea9ca76c422e12fedbfb6eb3b4#e331e2f488a368ea9ca76c422e12fedbfb6eb3b4" +source = "git+https://github.com/tempoxyz/tempo?rev=698f7cb1b3d057cf67bbd81b21af53dfeb231610#698f7cb1b3d057cf67bbd81b21af53dfeb231610" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10750,7 +10750,7 @@ dependencies = [ [[package]] name = "tempo-revm" version = "1.5.0" -source = "git+https://github.com/tempoxyz/tempo?rev=e331e2f488a368ea9ca76c422e12fedbfb6eb3b4#e331e2f488a368ea9ca76c422e12fedbfb6eb3b4" +source = "git+https://github.com/tempoxyz/tempo?rev=698f7cb1b3d057cf67bbd81b21af53dfeb231610#698f7cb1b3d057cf67bbd81b21af53dfeb231610" dependencies = [ "alloy-consensus", "alloy-evm", @@ -10773,7 +10773,7 @@ dependencies = [ [[package]] name = "tempo-transaction-pool" version = "1.5.0" -source = "git+https://github.com/tempoxyz/tempo?rev=e331e2f488a368ea9ca76c422e12fedbfb6eb3b4#e331e2f488a368ea9ca76c422e12fedbfb6eb3b4" +source = "git+https://github.com/tempoxyz/tempo?rev=698f7cb1b3d057cf67bbd81b21af53dfeb231610#698f7cb1b3d057cf67bbd81b21af53dfeb231610" dependencies = [ "alloy-consensus", "alloy-eips", diff --git a/Cargo.toml b/Cargo.toml index 3f6e6809b..39760fdd7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,23 +78,23 @@ codegen-units = 1 [workspace.dependencies] # tempo (from upstream) -tempo-alloy = { git = "https://github.com/tempoxyz/tempo", rev = "e331e2f488a368ea9ca76c422e12fedbfb6eb3b4" } -tempo-chainspec = { git = "https://github.com/tempoxyz/tempo", rev = "e331e2f488a368ea9ca76c422e12fedbfb6eb3b4", default-features = false } -tempo-consensus = { git = "https://github.com/tempoxyz/tempo", rev = "e331e2f488a368ea9ca76c422e12fedbfb6eb3b4", default-features = false } -tempo-contracts = { git = "https://github.com/tempoxyz/tempo", rev = "e331e2f488a368ea9ca76c422e12fedbfb6eb3b4", default-features = false, features = ["serde"] } -tempo-evm = { git = "https://github.com/tempoxyz/tempo", rev = "e331e2f488a368ea9ca76c422e12fedbfb6eb3b4", default-features = false } -tempo-node = { git = "https://github.com/tempoxyz/tempo", rev = "e331e2f488a368ea9ca76c422e12fedbfb6eb3b4" } -tempo-payload-types = { git = "https://github.com/tempoxyz/tempo", rev = "e331e2f488a368ea9ca76c422e12fedbfb6eb3b4", default-features = false } -tempo-precompiles = { git = "https://github.com/tempoxyz/tempo", rev = "e331e2f488a368ea9ca76c422e12fedbfb6eb3b4", default-features = false } -tempo-precompiles-macros = { git = "https://github.com/tempoxyz/tempo", rev = "e331e2f488a368ea9ca76c422e12fedbfb6eb3b4" } -tempo-primitives = { git = "https://github.com/tempoxyz/tempo", rev = "e331e2f488a368ea9ca76c422e12fedbfb6eb3b4", default-features = false, features = [ +tempo-alloy = { git = "https://github.com/tempoxyz/tempo", rev = "698f7cb1b3d057cf67bbd81b21af53dfeb231610" } +tempo-chainspec = { git = "https://github.com/tempoxyz/tempo", rev = "698f7cb1b3d057cf67bbd81b21af53dfeb231610", default-features = false } +tempo-consensus = { git = "https://github.com/tempoxyz/tempo", rev = "698f7cb1b3d057cf67bbd81b21af53dfeb231610", default-features = false } +tempo-contracts = { git = "https://github.com/tempoxyz/tempo", rev = "698f7cb1b3d057cf67bbd81b21af53dfeb231610", default-features = false, features = ["serde"] } +tempo-evm = { git = "https://github.com/tempoxyz/tempo", rev = "698f7cb1b3d057cf67bbd81b21af53dfeb231610", default-features = false } +tempo-node = { git = "https://github.com/tempoxyz/tempo", rev = "698f7cb1b3d057cf67bbd81b21af53dfeb231610" } +tempo-payload-types = { git = "https://github.com/tempoxyz/tempo", rev = "698f7cb1b3d057cf67bbd81b21af53dfeb231610", default-features = false } +tempo-precompiles = { git = "https://github.com/tempoxyz/tempo", rev = "698f7cb1b3d057cf67bbd81b21af53dfeb231610", default-features = false } +tempo-precompiles-macros = { git = "https://github.com/tempoxyz/tempo", rev = "698f7cb1b3d057cf67bbd81b21af53dfeb231610" } +tempo-primitives = { git = "https://github.com/tempoxyz/tempo", rev = "698f7cb1b3d057cf67bbd81b21af53dfeb231610", default-features = false, features = [ "reth", "serde", "serde-bincode-compat", "reth-codec", ] } -tempo-revm = { git = "https://github.com/tempoxyz/tempo", rev = "e331e2f488a368ea9ca76c422e12fedbfb6eb3b4", default-features = false } -tempo-transaction-pool = { git = "https://github.com/tempoxyz/tempo", rev = "e331e2f488a368ea9ca76c422e12fedbfb6eb3b4", default-features = false } +tempo-revm = { git = "https://github.com/tempoxyz/tempo", rev = "698f7cb1b3d057cf67bbd81b21af53dfeb231610", default-features = false } +tempo-transaction-pool = { git = "https://github.com/tempoxyz/tempo", rev = "698f7cb1b3d057cf67bbd81b21af53dfeb231610", default-features = false } # zones zone-precompiles = { path = "crates/precompiles", default-features = false } diff --git a/Justfile b/Justfile index a8c62d0de..4ddfcb964 100644 --- a/Justfile +++ b/Justfile @@ -587,6 +587,7 @@ zone-auth-token name: exit 1 fi ZONE_ID=$(jq -r '.zoneId' "$ZONE_JSON") + PORTAL=$(jq -r '.portal' "$ZONE_JSON") GENESIS_JSON="generated/{{name}}/genesis.json" CHAIN_ID=$(jq -r '.config.chainId' "$GENESIS_JSON") NOW=$(date +%s) @@ -595,9 +596,10 @@ zone-auth-token name: VERSION="00" ZONE_ID_HEX=$(printf '%08x' "$ZONE_ID") CHAIN_ID_HEX=$(printf '%016x' "$CHAIN_ID") + PORTAL_HEX=$(echo "$PORTAL" | sed 's/0x//' | tr '[:upper:]' '[:lower:]') ISSUED_HEX=$(printf '%016x' "$NOW") EXPIRES_HEX=$(printf '%016x' "$EXPIRES") - FIELDS="${VERSION}${ZONE_ID_HEX}${CHAIN_ID_HEX}${ISSUED_HEX}${EXPIRES_HEX}" + FIELDS="${VERSION}${ZONE_ID_HEX}${CHAIN_ID_HEX}${PORTAL_HEX}${ISSUED_HEX}${EXPIRES_HEX}" DIGEST=$(cast keccak "0x${MAGIC}${FIELDS}") SIG=$(cast wallet sign --no-hash "$DIGEST" --private-key "$PK") SIG_HEX=$(echo "$SIG" | sed 's/0x//') diff --git a/crates/precompiles/src/ztip20.rs b/crates/precompiles/src/ztip20.rs index 9108cd4b2..e57387e2b 100644 --- a/crates/precompiles/src/ztip20.rs +++ b/crates/precompiles/src/ztip20.rs @@ -21,7 +21,7 @@ use tempo_precompiles::{ storage::{StorageCtx, evm::EvmPrecompileStorageProvider}, tip20::{IRolesAuth, ITIP20, RolesAuthError, TIP20Token}, }; -use tracing::{trace, warn}; +use tracing::{debug, trace}; use zone_primitives::{ abi::Unauthorized, constants::{ZONE_INBOX_ADDRESS, ZONE_OUTBOX_ADDRESS}, @@ -217,12 +217,12 @@ impl ZoneTip20Token

{ let policy_id = match Self::resolve_transfer_policy_id(registry, token) { Ok(id) => id, Err(e) => { - warn!( + debug!( target: "zone::precompile", %token, error = %e, - "failed to resolve transfer_policy_id, rejecting transfer" + "failed to resolve transfer_policy_id, deferring to vanilla TIP20" ); - return Some(Err(e)); + return None; } }; @@ -248,17 +248,15 @@ impl ZoneTip20Token

{ /// Check mint recipient authorization. /// /// Returns `Some(revert)` if forbidden, `None` if allowed. - /// Resolution errors are treated as allow because mints are triggered by - /// deposit system transactions whose policy is already enforced on L1. fn enforce_mint(&self, token: Address, to: Address) -> Option { let registry = self.registry.as_ref()?; let policy_id = match Self::resolve_transfer_policy_id(registry, token) { Ok(id) => id, Err(e) => { - warn!( + debug!( target: "zone::precompile", %token, error = %e, - "failed to resolve transfer_policy_id for mint, deferring to L1 enforcement" + "failed to resolve transfer_policy_id, deferring to vanilla TIP20" ); return None; } @@ -438,7 +436,6 @@ mod tests { transfer_authorized: bool, mint_authorized: bool, policy_id: u64, - fail_policy_id_resolution: bool, } impl MockPolicyProvider { @@ -447,14 +444,6 @@ mod tests { transfer_authorized: true, mint_authorized: true, policy_id: 1, - fail_policy_id_resolution: false, - } - } - - fn failing() -> Self { - Self { - fail_policy_id_resolution: true, - ..Default::default() } } } @@ -474,9 +463,6 @@ mod tests { } fn resolve_transfer_policy_id(&self, _token: Address) -> Result { - if self.fail_policy_id_resolution { - return Err(PrecompileError::other("RPC unavailable")); - } Ok(self.policy_id) } @@ -1100,46 +1086,6 @@ mod tests { Ok(()) } - #[test] - fn transfer_fails_closed_on_policy_resolution_error() -> TestResult { - let mut harness = PrecompileHarness::new(MockPolicyProvider::failing())?; - - let calldata: Bytes = ITIP20::transferCall { - to: harness.bob, - amount: U256::from(100u64), - } - .abi_encode() - .into(); - - let result = harness.call(harness.alice, calldata, 100_000, false); - assert!( - result.is_err(), - "transfer must fail when policy resolution errors" - ); - - Ok(()) - } - - #[test] - fn mint_defers_to_l1_on_policy_resolution_error() -> TestResult { - let mut harness = PrecompileHarness::new(MockPolicyProvider::failing())?; - - let calldata: Bytes = ITIP20::mintCall { - to: harness.alice, - amount: U256::from(100u64), - } - .abi_encode() - .into(); - - let result = harness.call(harness.issuer, calldata, 100_000, false); - assert!( - result.is_ok(), - "mint must proceed when policy resolution errors (L1 enforces policy at deposit time)" - ); - - Ok(()) - } - #[test] fn has_role_enforces_account_or_sequencer_access() -> TestResult { let mut harness = PrecompileHarness::new(MockPolicyProvider::allow_all())?; diff --git a/crates/primitives/src/abi.rs b/crates/primitives/src/abi.rs index 78877b802..448910513 100644 --- a/crates/primitives/src/abi.rs +++ b/crates/primitives/src/abi.rs @@ -52,6 +52,7 @@ macro_rules! define_abi { address to; uint128 amount; bytes32 memo; + address bouncebackRecipient; } /// Encrypted deposit payload (ECIES encrypted recipient and memo) @@ -72,6 +73,7 @@ macro_rules! define_abi { uint128 amount; uint256 keyIndex; EncryptedDepositPayload encrypted; + address bouncebackRecipient; } #[derive(Debug)] @@ -120,7 +122,8 @@ macro_rules! define_abi { address to, uint128 netAmount, uint128 fee, - bytes32 memo + bytes32 memo, + address bouncebackRecipient ); #[derive(Debug)] @@ -155,13 +158,20 @@ macro_rules! define_abi { event WithdrawalProcessed(address indexed to, address token, uint128 amount, bool callbackSuccess); #[derive(Debug)] - event BounceBack( + event WithdrawalBounceBack( bytes32 indexed newCurrentDepositQueueHash, address indexed fallbackRecipient, address token, uint128 amount ); + #[derive(Debug)] + event DepositBounceBack( + address indexed bouncebackRecipient, + address token, + uint128 amount + ); + #[derive(Debug)] event SequencerTransferStarted( address indexed currentSequencer, @@ -734,6 +744,7 @@ mod tests { to: address!("0x0000000000000000000000000000000000000002"), amount: 1000u128, memo: B256::ZERO, + bouncebackRecipient: Address::ZERO, }; let encoded = d.abi_encode(); @@ -757,6 +768,7 @@ mod tests { to: address!("0x0000000000000000000000000000000000000002"), amount: 1000u128, memo: B256::ZERO, + bouncebackRecipient: Address::ZERO, }; let deposit_data = Bytes::from(deposit.abi_encode()); @@ -816,6 +828,7 @@ mod tests { to: address!("0x0000000000000000000000000000000000000002"), amount: 1000u128, memo: B256::ZERO, + bouncebackRecipient: Address::ZERO, }; let prev_hash = B256::ZERO; diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml index b662c426b..bce25a906 100644 --- a/crates/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] # tempo -tempo-alloy.workspace = true +tempo-alloy = { workspace = true, features = ["tempo-compat"] } tempo-contracts.workspace = true tempo-primitives.workspace = true diff --git a/crates/rpc/src/auth/token.rs b/crates/rpc/src/auth/token.rs index d0fe75d8e..7d4a0b7df 100644 --- a/crates/rpc/src/auth/token.rs +++ b/crates/rpc/src/auth/token.rs @@ -15,8 +15,9 @@ const TEMPO_ZONE_RPC_MAGIC: [u8; 32] = { buf }; -/// Size of the fixed token fields (version + zoneId + chainId + issuedAt + expiresAt). -const TOKEN_FIELDS_LEN: usize = 1 + 4 + 8 + 8 + 8; // 29 bytes +/// Size of the fixed token fields (version + zoneId + chainId + zonePortal + issuedAt + +/// expiresAt). +const TOKEN_FIELDS_LEN: usize = 1 + 4 + 8 + 20 + 8 + 8; // 49 bytes /// HTTP header name for the authorization token. pub const X_AUTHORIZATION_TOKEN: &str = "x-authorization-token"; @@ -34,23 +35,25 @@ pub struct AuthContext { /// Parsed authorization token fields (before signature verification). /// -/// The token is a hex-encoded blob: ``. -/// The last 29 bytes are always the fixed fields; everything before is the variable-length signature. +/// The token is a hex-encoded blob: ``. +/// The last 49 bytes are always the fixed fields; everything before is the variable-length signature. /// /// See `docs/pages/protocol/privacy/rpc.md` — "Transport" and "Message" sections. #[derive(Debug, Clone)] pub struct AuthorizationToken { /// Spec version (must be 0). pub version: u8, - /// Zone ID (0 = unscoped, valid for any zone). + /// Zone ID. pub zone_id: u32, /// Chain ID. pub chain_id: u64, + /// ZonePortal address on Tempo L1. + pub zone_portal: Address, /// Issuance timestamp (unix seconds). pub issued_at: u64, /// Expiry timestamp (unix seconds). pub expires_at: u64, - /// The raw signature bytes (everything before the last 29 bytes). + /// The raw signature bytes (everything before the last 49 bytes). pub signature: Vec, /// The signing digest (keccak256 of the packed message). pub digest: B256, @@ -73,8 +76,9 @@ impl AuthorizationToken { let version = fields[0]; let zone_id = u32::from_be_bytes(fields[1..5].try_into().unwrap()); let chain_id = u64::from_be_bytes(fields[5..13].try_into().unwrap()); - let issued_at = u64::from_be_bytes(fields[13..21].try_into().unwrap()); - let expires_at = u64::from_be_bytes(fields[21..29].try_into().unwrap()); + let zone_portal = Address::from_slice(&fields[13..33]); + let issued_at = u64::from_be_bytes(fields[33..41].try_into().unwrap()); + let expires_at = u64::from_be_bytes(fields[41..49].try_into().unwrap()); // Build the signing digest let mut msg = Vec::with_capacity(32 + TOKEN_FIELDS_LEN); @@ -82,6 +86,7 @@ impl AuthorizationToken { msg.push(version); msg.extend_from_slice(&zone_id.to_be_bytes()); msg.extend_from_slice(&chain_id.to_be_bytes()); + msg.extend_from_slice(zone_portal.as_slice()); msg.extend_from_slice(&issued_at.to_be_bytes()); msg.extend_from_slice(&expires_at.to_be_bytes()); let digest = keccak256(&msg); @@ -90,6 +95,7 @@ impl AuthorizationToken { version, zone_id, chain_id, + zone_portal, issued_at, expires_at, signature, @@ -98,19 +104,25 @@ impl AuthorizationToken { } /// Validate token fields against the server's zone configuration. - /// - /// A `zone_id` of `0` is unscoped and accepted for any zone. - pub fn validate(&self, expected_zone_id: u32, expected_chain_id: u64) -> Result<(), AuthError> { + pub fn validate( + &self, + expected_zone_id: u32, + expected_chain_id: u64, + expected_portal: Address, + ) -> Result<(), AuthError> { if self.version != 0 { return Err(AuthError::UnsupportedVersion(self.version)); } - if self.zone_id != 0 && self.zone_id != expected_zone_id { + if self.zone_id != expected_zone_id { return Err(AuthError::ZoneIdMismatch); } if self.chain_id != expected_chain_id { return Err(AuthError::ChainIdMismatch); } - if self.expires_at.saturating_sub(self.issued_at) > 2_592_000 { + if self.zone_portal != expected_portal { + return Err(AuthError::ZonePortalMismatch); + } + if self.expires_at.saturating_sub(self.issued_at) > 1800 { return Err(AuthError::WindowTooLarge); } @@ -132,13 +144,12 @@ impl AuthorizationToken { /// Build the unsigned token fields and their signing digest. /// -/// Returns `(fields, digest)` where `fields` is the 29-byte suffix +/// Returns `(fields, digest)` where `fields` is the 49-byte suffix /// and `digest` is the keccak256 hash to be signed. -/// -/// Pass `zone_id = 0` for an unscoped token valid for any zone. pub fn build_token_fields( zone_id: u32, chain_id: u64, + zone_portal: Address, issued_at: u64, expires_at: u64, ) -> ([u8; TOKEN_FIELDS_LEN], B256) { @@ -146,8 +157,9 @@ pub fn build_token_fields( fields[0] = 0; // version fields[1..5].copy_from_slice(&zone_id.to_be_bytes()); fields[5..13].copy_from_slice(&chain_id.to_be_bytes()); - fields[13..21].copy_from_slice(&issued_at.to_be_bytes()); - fields[21..29].copy_from_slice(&expires_at.to_be_bytes()); + fields[13..33].copy_from_slice(zone_portal.as_slice()); + fields[33..41].copy_from_slice(&issued_at.to_be_bytes()); + fields[41..49].copy_from_slice(&expires_at.to_be_bytes()); let mut msg = Vec::with_capacity(32 + TOKEN_FIELDS_LEN); msg.extend_from_slice(&TEMPO_ZONE_RPC_MAGIC); diff --git a/crates/rpc/src/config.rs b/crates/rpc/src/config.rs index 649856b43..ff0efdbfb 100644 --- a/crates/rpc/src/config.rs +++ b/crates/rpc/src/config.rs @@ -18,7 +18,7 @@ pub struct PrivateRpcConfig { pub zone_id: u32, /// The zone's chain ID. pub chain_id: u64, - /// The ZonePortal contract address on L1 (used for querying deposits, not for auth tokens). + /// The ZonePortal contract address on L1. pub zone_portal: Address, /// The sequencer address — callers matching this get unredacted responses. pub sequencer: Address, diff --git a/crates/rpc/src/error.rs b/crates/rpc/src/error.rs index 61e96fad7..5ea05a310 100644 --- a/crates/rpc/src/error.rs +++ b/crates/rpc/src/error.rs @@ -16,7 +16,9 @@ pub enum AuthError { ZoneIdMismatch, #[error("chain ID mismatch")] ChainIdMismatch, - #[error("validity window too large (max 2592000s)")] + #[error("zone portal mismatch")] + ZonePortalMismatch, + #[error("validity window too large (max 1800s)")] WindowTooLarge, #[error("authorization token expired")] Expired, diff --git a/crates/rpc/src/provider.rs b/crates/rpc/src/provider.rs index d0a570d5a..dab7fb780 100644 --- a/crates/rpc/src/provider.rs +++ b/crates/rpc/src/provider.rs @@ -9,7 +9,7 @@ use std::{ time::{Duration, SystemTime, UNIX_EPOCH}, }; -use alloy_primitives::hex; +use alloy_primitives::{Address, hex}; use alloy_provider::{DynProvider, Provider, ProviderBuilder}; use alloy_signer::SignerSync; use alloy_signer_local::PrivateKeySigner; @@ -33,7 +33,9 @@ pub struct ZoneProviderConfig { pub zone_id: u32, /// Chain identifier. pub chain_id: u64, - /// How long each generated token is valid. Default: 600s, max: 2592000s (30 days). + /// ZonePortal contract address on L1. + pub zone_portal: Address, + /// How long each generated token is valid. Default: 600s, max: 1800s. pub token_ttl: Duration, /// The private zone RPC URL. pub rpc_url: url::Url, @@ -105,14 +107,20 @@ fn build_provider_with_token( let now = now_secs(); let expires_at = now + config.token_ttl.as_secs(); - let (fields, digest) = build_token_fields(config.zone_id, config.chain_id, now, expires_at); + let (fields, digest) = build_token_fields( + config.zone_id, + config.chain_id, + config.zone_portal, + now, + expires_at, + ); let sig = config .signer .sign_hash_sync(&digest) .map_err(|e| eyre::eyre!("failed to sign zone auth token: {e}"))?; - // Build blob: <65-byte sig><29-byte fields> + // Build blob: <65-byte sig><49-byte fields> let mut blob = Vec::with_capacity(65 + fields.len()); blob.extend_from_slice(&sig.r().to_be_bytes::<32>()); blob.extend_from_slice(&sig.s().to_be_bytes::<32>()); diff --git a/crates/rpc/src/server.rs b/crates/rpc/src/server.rs index 7bb7b7801..c5c7b3998 100644 --- a/crates/rpc/src/server.rs +++ b/crates/rpc/src/server.rs @@ -219,7 +219,7 @@ pub(crate) async fn authenticate_token( let token = auth::parse_auth_header(token_value)?; // Validate token fields against server config - token.validate(config.zone_id, config.chain_id)?; + token.validate(config.zone_id, config.chain_id, config.zone_portal)?; let signature = TempoSignature::from_bytes(&token.signature).map_err(|_| AuthError::InvalidSignature)?; @@ -400,7 +400,7 @@ mod tests { let root_account = Address::repeat_byte(0x55); let access_signer = P256SigningKey::random(&mut thread_rng()); let now = now_secs(); - let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, now, now + 600); + let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, PORTAL, now, now + 600); let (signature, key_id) = sign_keychain_signature(digest, &access_signer, root_account, 0x04) .expect("keychain signing failed"); diff --git a/crates/rpc/tests/it/ws.rs b/crates/rpc/tests/it/ws.rs index 4017ac1ec..8a33890b3 100644 --- a/crates/rpc/tests/it/ws.rs +++ b/crates/rpc/tests/it/ws.rs @@ -269,6 +269,7 @@ impl ZoneRpcApi for MockZoneRpcApi { const ZONE_ID: u32 = 1; const CHAIN_ID: u64 = 42; +const PORTAL: Address = Address::ZERO; struct TestContext { addr: std::net::SocketAddr, @@ -285,7 +286,7 @@ impl TestContext { retry_connection_interval: std::time::Duration::from_millis(100), zone_id: ZONE_ID, chain_id: CHAIN_ID, - zone_portal: Address::ZERO, + zone_portal: PORTAL, sequencer: signer.address(), }; let addr = start_private_rpc(config, Arc::new(api)).await.unwrap(); @@ -294,7 +295,7 @@ impl TestContext { fn build_token(&self) -> String { let now = now_secs(); - let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, now, now + 600); + let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, PORTAL, now, now + 600); let sig = self.signer.sign_hash_sync(&digest).expect("signing failed"); let mut blob = Vec::with_capacity(65 + fields.len()); @@ -792,7 +793,7 @@ async fn ws_roundtrip_with_p256_auth() { let ctx = TestContext::start(MockZoneRpcApi::default()).await; let signing_key = P256SigningKey::random(&mut thread_rng()); let now = now_secs(); - let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, now, now + 600); + let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, PORTAL, now, now + 600); let token = build_token_with_signature( sign_p256_signature(digest, &signing_key).expect("p256 signing should succeed"), &fields, @@ -817,7 +818,7 @@ async fn ws_roundtrip_with_webauthn_auth() { let ctx = TestContext::start(MockZoneRpcApi::default()).await; let signing_key = P256SigningKey::random(&mut thread_rng()); let now = now_secs(); - let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, now, now + 600); + let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, PORTAL, now, now + 600); let token = build_token_with_signature( sign_webauthn_signature(&signing_key, digest).expect("webauthn signing should succeed"), &fields, @@ -842,7 +843,7 @@ async fn ws_roundtrip_with_keychain_auth() { let root_account = Address::repeat_byte(0x55); let access_signer = P256SigningKey::random(&mut thread_rng()); let now = now_secs(); - let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, now, now + 600); + let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, PORTAL, now, now + 600); let (signature, key_id) = sign_keychain_signature(digest, &access_signer, root_account, 0x04) .expect("keychain signing should succeed"); let ctx = TestContext::start(MockZoneRpcApi::with_key( @@ -873,7 +874,7 @@ async fn ws_reject_unauthorized_keychain_token() { let access_signer = P256SigningKey::random(&mut thread_rng()); let ctx = TestContext::start(MockZoneRpcApi::default()).await; let now = now_secs(); - let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, now, now + 600); + let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, PORTAL, now, now + 600); let (signature, _key_id) = sign_keychain_signature(digest, &access_signer, root_account, 0x04) .expect("keychain signing should succeed"); let token = build_token_with_signature(signature, &fields); @@ -893,7 +894,7 @@ async fn ws_keychain_lookup_failure_returns_500() { let access_signer = P256SigningKey::random(&mut thread_rng()); let ctx = TestContext::start(MockZoneRpcApi::with_key_lookup_error("key lookup failed")).await; let now = now_secs(); - let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, now, now + 600); + let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, PORTAL, now, now + 600); let (signature, _key_id) = sign_keychain_signature(digest, &access_signer, root_account, 0x04) .expect("keychain signing should succeed"); let token = build_token_with_signature(signature, &fields); diff --git a/crates/tempo-zone/Cargo.toml b/crates/tempo-zone/Cargo.toml index 9f6cffc43..e360bf747 100644 --- a/crates/tempo-zone/Cargo.toml +++ b/crates/tempo-zone/Cargo.toml @@ -20,7 +20,7 @@ tempo-node.workspace = true tempo-payload-types.workspace = true tempo-primitives.workspace = true tempo-transaction-pool.workspace = true -tempo-alloy.workspace = true +tempo-alloy = { workspace = true, features = ["tempo-compat"] } tempo-contracts.workspace = true tempo-precompiles.workspace = true zone-precompiles = { workspace = true, features = ["std"] } diff --git a/crates/tempo-zone/src/builder.rs b/crates/tempo-zone/src/builder.rs index b168c03c4..4a606ace5 100644 --- a/crates/tempo-zone/src/builder.rs +++ b/crates/tempo-zone/src/builder.rs @@ -594,7 +594,7 @@ pub fn build_advance_tempo_tx(prepared: &PreparedL1Block) -> Recovered Self { + pub fn from_bounce_back(event: WithdrawalBounceBack, portal_address: Address) -> Self { Self { token: event.token, sender: portal_address, @@ -811,6 +814,7 @@ impl Deposit { amount: event.amount, fee: 0, memo: B256::ZERO, + bounceback_recipient: Address::ZERO, } } } @@ -838,6 +842,8 @@ pub struct EncryptedDeposit { pub nonce: [u8; 12], /// GCM authentication tag (16 bytes). pub tag: [u8; 16], + /// Bounceback recipient on L1 (receives funds if the zone rejects the deposit). + pub bounceback_recipient: Address, } impl EncryptedDeposit { @@ -854,6 +860,7 @@ impl EncryptedDeposit { ciphertext: event.ciphertext.to_vec(), nonce: event.nonce.0, tag: event.tag.0, + bounceback_recipient: Address::ZERO, } } } @@ -880,6 +887,7 @@ impl L1Deposit { to: d.to, amount: d.amount, memo: d.memo, + bouncebackRecipient: d.bounceback_recipient, }, prev_hash, ) @@ -900,6 +908,7 @@ impl L1Deposit { nonce: d.nonce.into(), tag: d.tag.into(), }, + bouncebackRecipient: d.bounceback_recipient, }, prev_hash, ) @@ -981,7 +990,7 @@ impl L1PortalEvents { const SIGNATURE_HASHES: [B256; 6] = [ DepositMade::SIGNATURE_HASH, EncryptedDepositMade::SIGNATURE_HASH, - BounceBack::SIGNATURE_HASH, + WithdrawalBounceBack::SIGNATURE_HASH, TokenEnabled::SIGNATURE_HASH, SequencerTransferStarted::SIGNATURE_HASH, SequencerTransferred::SIGNATURE_HASH, @@ -1032,7 +1041,7 @@ impl L1PortalEvents { self.deposits .push(L1Deposit::Encrypted(EncryptedDeposit::from_event(event))); } - ZonePortalEvents::BounceBack(event) => { + ZonePortalEvents::WithdrawalBounceBack(event) => { info!( l1_block = block_number, token = %event.token, @@ -1143,6 +1152,7 @@ impl L1BlockDeposits { to: d.to, amount: d.amount, memo: d.memo, + bouncebackRecipient: d.bounceback_recipient, }; queued_deposits.push(abi::QueuedDeposit { depositType: abi::DepositType::Regular, @@ -1165,6 +1175,7 @@ impl L1BlockDeposits { nonce: d.nonce.into(), tag: d.tag.into(), }, + bouncebackRecipient: d.bounceback_recipient, } .abi_encode(), ), @@ -1939,7 +1950,7 @@ mod tests { let portal_address = address!("0x0000000000000000000000000000000000000ABC"); let fallback_recipient = address!("0x00000000000000000000000000000000000000F1"); let token = address!("0x0000000000000000000000000000000000002000"); - let event = BounceBack { + let event = WithdrawalBounceBack { newCurrentDepositQueueHash: B256::with_last_byte(0x42), fallbackRecipient: fallback_recipient, token, @@ -2138,6 +2149,7 @@ mod tests { amount: 1000, fee: 0, memo: B256::ZERO, + bounceback_recipient: Address::ZERO, }); queue.enqueue( @@ -2164,6 +2176,7 @@ mod tests { amount: 2000, fee: 0, memo: B256::ZERO, + bounceback_recipient: Address::ZERO, }); queue.enqueue( @@ -2185,6 +2198,7 @@ mod tests { amount: 1000, fee: 0, memo: B256::ZERO, + bounceback_recipient: Address::ZERO, }), L1Deposit::Regular(Deposit { token: address!("0x0000000000000000000000000000000000001000"), @@ -2193,6 +2207,7 @@ mod tests { amount: 2000, fee: 0, memo: B256::ZERO, + bounceback_recipient: Address::ZERO, }), ]; @@ -2224,6 +2239,7 @@ mod tests { amount: 500, fee: 0, memo: FixedBytes::from([0xABu8; 32]), + bounceback_recipient: Address::ZERO, })]; queue.enqueue( @@ -2248,6 +2264,7 @@ mod tests { amount: 100, fee: 0, memo: B256::ZERO, + bounceback_recipient: Address::ZERO, }); let d2 = L1Deposit::Regular(Deposit { @@ -2257,6 +2274,7 @@ mod tests { amount: 200, fee: 0, memo: B256::ZERO, + bounceback_recipient: Address::ZERO, }); let h10 = make_test_header(10); @@ -2295,6 +2313,7 @@ mod tests { ciphertext: vec![0x42u8; 64], nonce: [0x01; 12], tag: [0x02; 16], + bounceback_recipient: Address::ZERO, }; // Compute via PendingDeposits (Rust implementation) @@ -2314,6 +2333,7 @@ mod tests { nonce: encrypted.nonce.into(), tag: encrypted.tag.into(), }, + bouncebackRecipient: Address::ZERO, }; let expected = keccak256((DepositType::Encrypted, abi_encrypted, B256::ZERO).abi_encode()); @@ -2341,6 +2361,7 @@ mod tests { amount: 500_000, fee: 0, memo: B256::ZERO, + bounceback_recipient: Address::ZERO, }; let encrypted = EncryptedDeposit { @@ -2354,6 +2375,7 @@ mod tests { ciphertext: vec![0x55u8; 64], nonce: [0x0A; 12], tag: [0x0B; 16], + bounceback_recipient: Address::ZERO, }; let deposits = vec![ @@ -2373,6 +2395,7 @@ mod tests { to: regular.to, amount: regular.amount, memo: regular.memo, + bouncebackRecipient: Address::ZERO, }, B256::ZERO, ) @@ -2394,6 +2417,7 @@ mod tests { nonce: encrypted.nonce.into(), tag: encrypted.tag.into(), }, + bouncebackRecipient: Address::ZERO, }, hash_1, ) @@ -2420,6 +2444,7 @@ mod tests { ciphertext: vec![0x99u8; 64], nonce: [0x03; 12], tag: [0x04; 16], + bounceback_recipient: Address::ZERO, }; let deposits = vec![L1Deposit::Encrypted(encrypted)]; @@ -2640,6 +2665,7 @@ mod tests { amount: 100, fee: 0, memo: B256::ZERO, + bounceback_recipient: Address::ZERO, }); assert!(matches!( queue.try_enqueue(seal(h1), L1PortalEvents::from_deposits(vec![d1]), vec![]), @@ -2655,6 +2681,7 @@ mod tests { amount: 200, fee: 0, memo: B256::ZERO, + bounceback_recipient: Address::ZERO, }); assert!(matches!( queue.try_enqueue(seal(h2), L1PortalEvents::from_deposits(vec![d2]), vec![]), @@ -2688,6 +2715,7 @@ mod tests { amount, fee: 0, memo: B256::ZERO, + bounceback_recipient: Address::ZERO, }) } diff --git a/crates/tempo-zone/tests/advance_tempo.rs b/crates/tempo-zone/tests/advance_tempo.rs index 1a305571a..d71bbb826 100644 --- a/crates/tempo-zone/tests/advance_tempo.rs +++ b/crates/tempo-zone/tests/advance_tempo.rs @@ -189,12 +189,13 @@ fn setup_zone_evm_with_contracts() -> TempoEvm> { ); nonce += 1; - // 3. ZoneInbox(address config, address tempoPortal, address tempoState) + // 3. ZoneInbox(address config, address tempoPortal, address tempoState, address outbox) let zone_inbox_bytecode = load_artifact("ZoneInbox"); let zone_inbox_args = alloy_sol_types::SolValue::abi_encode_params(&( ZONE_CONFIG_ADDRESS, tempo_portal, TEMPO_STATE_ADDRESS, + ZONE_OUTBOX_ADDRESS, )); deploy_contract( &mut evm, diff --git a/crates/tempo-zone/tests/it/private_rpc.rs b/crates/tempo-zone/tests/it/private_rpc.rs index 9a0b88ab7..7086ca2ea 100644 --- a/crates/tempo-zone/tests/it/private_rpc.rs +++ b/crates/tempo-zone/tests/it/private_rpc.rs @@ -21,10 +21,13 @@ fn build_token_blob( version: u8, zone_id: u32, chain_id: u64, + portal: Address, issued_at: u64, expires_at: u64, ) -> Vec { - let (mut fields, _digest) = build_token_fields(zone_id, chain_id, issued_at, expires_at); + let (mut fields, _digest) = + build_token_fields(zone_id, chain_id, portal, issued_at, expires_at); + // build_token_fields always sets version=0; override for tests that need a different version. fields[0] = version; let mut blob = vec![0u8; 65]; // fake secp256k1 sig blob.extend_from_slice(&fields); @@ -35,10 +38,11 @@ fn make_test_token( version: u8, zone_id: u32, chain_id: u64, + portal: Address, issued_at: u64, expires_at: u64, ) -> AuthorizationToken { - let blob = build_token_blob(version, zone_id, chain_id, issued_at, expires_at); + let blob = build_token_blob(version, zone_id, chain_id, portal, issued_at, expires_at); AuthorizationToken::parse(&blob).unwrap() } @@ -47,12 +51,14 @@ fn make_test_token( #[test] fn parse_token_fields() { let now = now_secs(); + let portal = Address::repeat_byte(0xAA); - let token = make_test_token(0, 42, 1337, now, now + 600); + let token = make_test_token(0, 42, 1337, portal, now, now + 600); assert_eq!(token.version, 0); assert_eq!(token.zone_id, 42); assert_eq!(token.chain_id, 1337); + assert_eq!(token.zone_portal, portal); assert_eq!(token.issued_at, now); assert_eq!(token.expires_at, now + 600); assert_eq!(token.signature.len(), 65); @@ -60,8 +66,8 @@ fn parse_token_fields() { #[test] fn parse_token_too_short() { - // 29 bytes = exactly the message length, no room for a signature - let blob = vec![0u8; 29]; + // 49 bytes = exactly the message length, no room for a signature + let blob = vec![0u8; 49]; assert!(AuthorizationToken::parse(&blob).is_err()); // Even shorter @@ -72,10 +78,11 @@ fn parse_token_too_short() { fn parse_unknown_signature_length() { // 50-byte signature (not 65 or 130, and first byte is not 0x02/0x03) → should error let mut blob = vec![0u8; 50]; - // 29 bytes of fields + // 49 bytes of fields blob.push(0); blob.extend_from_slice(&1u32.to_be_bytes()); blob.extend_from_slice(&1u64.to_be_bytes()); + blob.extend_from_slice(&[0u8; 20]); let now = now_secs(); blob.extend_from_slice(&now.to_be_bytes()); blob.extend_from_slice(&(now + 600).to_be_bytes()); @@ -86,15 +93,17 @@ fn parse_unknown_signature_length() { #[test] fn digest_is_deterministic() { - let t1 = make_test_token(0, 1, 2, 1000, 1600); - let t2 = make_test_token(0, 1, 2, 1000, 1600); + let portal = Address::repeat_byte(0xCC); + let t1 = make_test_token(0, 1, 2, portal, 1000, 1600); + let t2 = make_test_token(0, 1, 2, portal, 1000, 1600); assert_eq!(t1.digest, t2.digest); } #[test] fn digest_changes_with_params() { - let t1 = make_test_token(0, 1, 2, 1000, 1600); - let t3 = make_test_token(0, 1, 3, 1000, 1600); + let portal = Address::repeat_byte(0xCC); + let t1 = make_test_token(0, 1, 2, portal, 1000, 1600); + let t3 = make_test_token(0, 1, 3, portal, 1000, 1600); assert_ne!(t1.digest, t3.digest); } @@ -103,60 +112,69 @@ fn digest_changes_with_params() { #[test] fn validate_accepts_valid_token() { let now = now_secs(); - let token = make_test_token(0, 42, 1337, now, now + 600); - assert!(token.validate(42, 1337).is_ok()); + let portal = Address::repeat_byte(0xBB); + let token = make_test_token(0, 42, 1337, portal, now, now + 600); + assert!(token.validate(42, 1337, portal).is_ok()); } #[test] fn validate_rejects_wrong_version() { let now = now_secs(); - let token = make_test_token(1, 42, 1337, now, now + 600); - assert!(token.validate(42, 1337).is_err()); + let portal = Address::repeat_byte(0xBB); + let token = make_test_token(1, 42, 1337, portal, now, now + 600); + assert!(token.validate(42, 1337, portal).is_err()); } #[test] fn validate_rejects_zone_id_mismatch() { let now = now_secs(); - let token = make_test_token(0, 42, 1337, now, now + 600); - assert!(token.validate(99, 1337).is_err()); + let portal = Address::repeat_byte(0xBB); + let token = make_test_token(0, 42, 1337, portal, now, now + 600); + assert!(token.validate(99, 1337, portal).is_err()); } #[test] -fn validate_accepts_unscoped_zone_id() { +fn validate_rejects_chain_id_mismatch() { let now = now_secs(); - let token = make_test_token(0, 0, 1337, now, now + 600); - assert!(token.validate(42, 1337).is_ok()); - assert!(token.validate(99, 1337).is_ok()); + let portal = Address::repeat_byte(0xBB); + let token = make_test_token(0, 42, 1337, portal, now, now + 600); + assert!(token.validate(42, 9999, portal).is_err()); } #[test] -fn validate_rejects_chain_id_mismatch() { +fn validate_rejects_portal_mismatch() { let now = now_secs(); - let token = make_test_token(0, 42, 1337, now, now + 600); - assert!(token.validate(42, 9999).is_err()); + let portal = Address::repeat_byte(0xBB); + let other = Address::repeat_byte(0xCC); + let token = make_test_token(0, 42, 1337, portal, now, now + 600); + assert!(token.validate(42, 1337, other).is_err()); } #[test] fn validate_rejects_expired() { let now = now_secs(); - let token = make_test_token(0, 42, 1337, now - 700, now - 100); - assert!(token.validate(42, 1337).is_err()); + let portal = Address::repeat_byte(0xBB); + // Token that expired 100s ago + let token = make_test_token(0, 42, 1337, portal, now - 700, now - 100); + assert!(token.validate(42, 1337, portal).is_err()); } #[test] fn validate_rejects_window_too_large() { let now = now_secs(); - // 31 days > 30-day max - let token = make_test_token(0, 42, 1337, now, now + 31 * 86400); - assert!(token.validate(42, 1337).is_err()); + let portal = Address::repeat_byte(0xBB); + // 2000s window > 1800s max + let token = make_test_token(0, 42, 1337, portal, now, now + 2000); + assert!(token.validate(42, 1337, portal).is_err()); } #[test] fn validate_rejects_issued_at_far_future() { let now = now_secs(); + let portal = Address::repeat_byte(0xBB); // issuedAt is 200s in the future (> 60s max skew) - let token = make_test_token(0, 42, 1337, now + 200, now + 800); - assert!(token.validate(42, 1337).is_err()); + let token = make_test_token(0, 42, 1337, portal, now + 200, now + 800); + assert!(token.validate(42, 1337, portal).is_err()); } #[tokio::test] @@ -165,7 +183,7 @@ async fn tempo_signature_roundtrip_secp256k1_from_token_bytes() { let signer = PrivateKeySigner::random(); let now = now_secs(); - let (fields, digest) = build_token_fields(1, 2, now, now + 600); + let (fields, digest) = build_token_fields(1, 2, Address::ZERO, now, now + 600); let sig = signer.sign_hash(&digest).await.unwrap(); let mut sig_bytes = Vec::with_capacity(65); @@ -197,7 +215,7 @@ fn tempo_signature_rejects_wrong_secp256k1_lengths() { fn tempo_signature_roundtrip_p256_from_token_bytes() { let signing_key = P256SigningKey::random(&mut thread_rng()); let now = now_secs(); - let (fields, digest) = build_token_fields(1, 2, now, now + 600); + let (fields, digest) = build_token_fields(1, 2, Address::ZERO, now, now + 600); let expected = sign_p256_signature(digest, &signing_key) .expect("p256 signing should succeed") .recover_signer(&digest) @@ -216,7 +234,7 @@ fn tempo_signature_roundtrip_p256_from_token_bytes() { fn tempo_signature_roundtrip_webauthn_from_token_bytes() { let signing_key = P256SigningKey::random(&mut thread_rng()); let now = now_secs(); - let (fields, digest) = build_token_fields(1, 2, now, now + 600); + let (fields, digest) = build_token_fields(1, 2, Address::ZERO, now, now + 600); let signature = sign_webauthn_signature(&signing_key, digest).expect("webauthn signing should succeed"); let expected = signature @@ -234,7 +252,7 @@ fn tempo_signature_roundtrip_keychain_v1_from_token_bytes() { let signing_key = P256SigningKey::random(&mut thread_rng()); let root_account = Address::repeat_byte(0x44); let now = now_secs(); - let (fields, digest) = build_token_fields(1, 2, now, now + 600); + let (fields, digest) = build_token_fields(1, 2, Address::ZERO, now, now + 600); let (signature, expected_key_id) = sign_keychain_signature(digest, &signing_key, root_account, 0x03) .expect("keychain signing should succeed"); @@ -256,7 +274,7 @@ fn tempo_signature_roundtrip_keychain_v2_from_token_bytes() { let signing_key = P256SigningKey::random(&mut thread_rng()); let root_account = Address::repeat_byte(0x55); let now = now_secs(); - let (fields, digest) = build_token_fields(1, 2, now, now + 600); + let (fields, digest) = build_token_fields(1, 2, Address::ZERO, now, now + 600); let (signature, expected_key_id) = sign_keychain_signature(digest, &signing_key, root_account, 0x04) .expect("keychain signing should succeed"); diff --git a/crates/tempo-zone/tests/it/private_rpc_e2e.rs b/crates/tempo-zone/tests/it/private_rpc_e2e.rs index e72df4857..646580069 100644 --- a/crates/tempo-zone/tests/it/private_rpc_e2e.rs +++ b/crates/tempo-zone/tests/it/private_rpc_e2e.rs @@ -172,7 +172,12 @@ async fn test_auth_rejection() -> eyre::Result<()> { ); // Valid signature but wrong chain ID → 403 - let bad_token = ctx.build_bad_token(&ctx.sequencer_signer, 1, ctx.config.chain_id + 1); + let bad_token = ctx.build_bad_token( + &ctx.sequencer_signer, + 0, + ctx.config.chain_id + 1, + Address::ZERO, + ); let (status, _) = ctx .call_raw("eth_blockNumber", serde_json::json!([]), &bad_token) .await?; diff --git a/crates/tempo-zone/tests/it/utils.rs b/crates/tempo-zone/tests/it/utils.rs index 6e5beafa1..71651e568 100644 --- a/crates/tempo-zone/tests/it/utils.rs +++ b/crates/tempo-zone/tests/it/utils.rs @@ -2216,14 +2216,6 @@ pub(crate) async fn start_local_zone_with_fixture( ) -> eyre::Result<(ZoneTestNode, L1Fixture)> { let zone = ZoneTestNode::start_local().await?; let fixture = L1Fixture::new(); - - // Local tests have no real L1, so the RPC fallback in resolve_transfer_policy_id - // fails. Seed pathUSD with the default allow-all policy (mirrors L1 default). - use tempo_precompiles::{PATH_USD_ADDRESS, tip403_registry::ALLOW_ALL_POLICY_ID}; - zone.policy_cache() - .write() - .set_token_policy(PATH_USD_ADDRESS, 0, ALLOW_ALL_POLICY_ID); - fixture.seed_l1_cache( zone.l1_state_cache(), Address::ZERO, @@ -2255,6 +2247,7 @@ fn build_auth_token( signer: &alloy_signer_local::PrivateKeySigner, zone_id: u32, chain_id: u64, + portal: Address, ) -> String { use alloy_signer::SignerSync; use zone::rpc::auth::build_token_fields; @@ -2262,7 +2255,7 @@ fn build_auth_token( let now = now_secs(); let expires_at = now + 600; - let (fields, digest) = build_token_fields(zone_id, chain_id, now, expires_at); + let (fields, digest) = build_token_fields(zone_id, chain_id, portal, now, expires_at); let sig = signer.sign_hash_sync(&digest).expect("signing failed"); let mut blob = Vec::with_capacity(65 + fields.len()); @@ -2278,24 +2271,32 @@ fn build_auth_token_with_signature( signature: TempoSignature, zone_id: u32, chain_id: u64, + portal: Address, ) -> String { use zone::rpc::auth::build_token_fields; let now = now_secs(); let expires_at = now + 600; - let (fields, _) = build_token_fields(zone_id, chain_id, now, expires_at); + let (fields, _) = build_token_fields(zone_id, chain_id, portal, now, expires_at); auth_tokens::build_token_with_signature(signature, &fields) } -fn build_p256_auth_token(signing_key: &P256SigningKey, zone_id: u32, chain_id: u64) -> String { +fn build_p256_auth_token( + signing_key: &P256SigningKey, + zone_id: u32, + chain_id: u64, + portal: Address, +) -> String { let now = now_secs(); let expires_at = now + 600; - let (_, digest) = zone::rpc::auth::build_token_fields(zone_id, chain_id, now, expires_at); + let (_, digest) = + zone::rpc::auth::build_token_fields(zone_id, chain_id, portal, now, expires_at); build_auth_token_with_signature( sign_p256_signature(digest, signing_key).expect("p256 signing failed"), zone_id, chain_id, + portal, ) } @@ -2303,16 +2304,19 @@ fn build_webauthn_auth_token( signing_key: &P256SigningKey, zone_id: u32, chain_id: u64, + portal: Address, challenge_digest: Option, ) -> String { let now = now_secs(); let expires_at = now + 600; - let (_, digest) = zone::rpc::auth::build_token_fields(zone_id, chain_id, now, expires_at); + let (_, digest) = + zone::rpc::auth::build_token_fields(zone_id, chain_id, portal, now, expires_at); build_auth_token_with_signature( sign_webauthn_signature(signing_key, challenge_digest.unwrap_or(digest)) .expect("webauthn signing failed"), zone_id, chain_id, + portal, ) } @@ -2322,15 +2326,17 @@ fn build_keychain_auth_token( version: u8, zone_id: u32, chain_id: u64, + portal: Address, ) -> (String, Address) { let now = now_secs(); let expires_at = now + 600; - let (_, digest) = zone::rpc::auth::build_token_fields(zone_id, chain_id, now, expires_at); + let (_, digest) = + zone::rpc::auth::build_token_fields(zone_id, chain_id, portal, now, expires_at); let (signature, key_id) = sign_keychain_signature(digest, signing_key, root_account, version) .expect("keychain signing failed"); ( - build_auth_token_with_signature(signature, zone_id, chain_id), + build_auth_token_with_signature(signature, zone_id, chain_id, portal), key_id, ) } @@ -2471,22 +2477,39 @@ impl PrivateRpcTestCtx { &self.sequencer_signer, self.config.zone_id, self.config.chain_id, + self.config.zone_portal, ) } /// Build an auth token for a regular (non-sequencer) user. pub(crate) fn user_token(&self, signer: &alloy_signer_local::PrivateKeySigner) -> String { - build_auth_token(signer, self.config.zone_id, self.config.chain_id) + build_auth_token( + signer, + self.config.zone_id, + self.config.chain_id, + self.config.zone_portal, + ) } /// Build a P256 auth token for a non-sequencer caller. pub(crate) fn p256_token(&self, signing_key: &P256SigningKey) -> String { - build_p256_auth_token(signing_key, self.config.zone_id, self.config.chain_id) + build_p256_auth_token( + signing_key, + self.config.zone_id, + self.config.chain_id, + self.config.zone_portal, + ) } /// Build a WebAuthn auth token for a non-sequencer caller. pub(crate) fn webauthn_token(&self, signing_key: &P256SigningKey) -> String { - build_webauthn_auth_token(signing_key, self.config.zone_id, self.config.chain_id, None) + build_webauthn_auth_token( + signing_key, + self.config.zone_id, + self.config.chain_id, + self.config.zone_portal, + None, + ) } /// Build a WebAuthn auth token with an overridden challenge digest. @@ -2499,6 +2522,7 @@ impl PrivateRpcTestCtx { signing_key, self.config.zone_id, self.config.chain_id, + self.config.zone_portal, Some(challenge_digest), ) } @@ -2516,6 +2540,7 @@ impl PrivateRpcTestCtx { version, self.config.zone_id, self.config.chain_id, + self.config.zone_portal, ) } @@ -2569,14 +2594,15 @@ impl PrivateRpcTestCtx { private_rpc_call_no_auth(&self.private_rpc_url, method, params).await } - /// Build an auth token with custom zone_id and chain_id (for negative testing). + /// Build an auth token with custom zone_id, chain_id, and portal (for negative testing). pub(crate) fn build_bad_token( &self, signer: &alloy_signer_local::PrivateKeySigner, zone_id: u32, chain_id: u64, + portal: Address, ) -> String { - build_auth_token(signer, zone_id, chain_id) + build_auth_token(signer, zone_id, chain_id, portal) } /// Inject an empty L1 block and wait for it to be processed. @@ -2998,6 +3024,7 @@ impl L1Fixture { amount, fee: 0, memo: B256::ZERO, + bounceback_recipient: Address::ZERO, } } @@ -3064,6 +3091,7 @@ impl L1Fixture { ciphertext: vec![0u8; 64], // ENCRYPTED_PAYLOAD_PLAINTEXT_SIZE = 64 nonce: [0u8; 12], tag: [0u8; 16], + bounceback_recipient: Address::ZERO, } } @@ -3082,6 +3110,7 @@ impl L1Fixture { amount, fee: 0, memo: B256::ZERO, + bounceback_recipient: Address::ZERO, } } @@ -3143,6 +3172,7 @@ impl L1Fixture { ciphertext, nonce, tag, + bounceback_recipient: Address::ZERO, } } } diff --git a/docs/pages/protocol/privacy/overview.md b/docs/pages/protocol/privacy/overview.md index 6f31023c9..321cdde98 100644 --- a/docs/pages/protocol/privacy/overview.md +++ b/docs/pages/protocol/privacy/overview.md @@ -367,6 +367,7 @@ struct Deposit { address to; uint128 amount; bytes32 memo; + address bouncebackRecipient; // L1 address for refund if zone-side processing fails (address(0) for bounce-back deposits) } struct Withdrawal { @@ -511,7 +512,8 @@ interface IZonePortal { address to, uint128 netAmount, uint128 fee, - bytes32 memo + bytes32 memo, + address bouncebackRecipient ); event BatchSubmitted( @@ -527,12 +529,18 @@ interface IZonePortal { bool callbackSuccess ); - event BounceBack( + event WithdrawalBounceBack( bytes32 indexed newCurrentDepositQueueHash, address indexed fallbackRecipient, uint128 amount ); + event DepositBounceBack( + address indexed token, + address indexed bouncebackRecipient, + uint128 amount + ); + event SequencerTransferStarted(address indexed currentSequencer, address indexed pendingSequencer); event SequencerTransferred(address indexed previousSequencer, address indexed newSequencer); @@ -611,14 +619,17 @@ interface IZonePortal { function calculateDepositFee() external view returns (uint128 fee); /// @notice Deposit a TIP-20 token into the zone. Fee is deducted from amount. - function deposit(address token, address to, uint128 amount, bytes32 memo) external returns (bytes32 newCurrentDepositQueueHash); + /// @param bouncebackRecipient L1 address to receive refund if zone-side processing fails. Validated against TIP-403 at deposit time. + function deposit(address token, address to, uint128 amount, bytes32 memo, address bouncebackRecipient) external returns (bytes32 newCurrentDepositQueueHash); /// @notice Deposit with encrypted recipient and memo. Fee is deducted from amount. + /// @param bouncebackRecipient L1 address to receive refund if zone-side processing fails. Validated against TIP-403 at deposit time. function depositEncrypted( address token, uint128 amount, uint256 keyIndex, - EncryptedDepositPayload calldata encrypted + EncryptedDepositPayload calldata encrypted, + address bouncebackRecipient ) external returns (bytes32 newCurrentDepositQueueHash); /// @notice Get the current sequencer encryption key. @@ -1139,15 +1150,17 @@ The key insight: structure the hash chain so the **on-chain operation touches th ## Bridging in (Tempo to zone) -1. User calls `ZonePortal.deposit(token, to, amount, memo)` on Tempo, specifying which enabled TIP-20 to deposit. -2. `ZonePortal` validates the token is enabled and deposits are active, transfers `amount` of the specified token into escrow, and appends a deposit to the queue: `currentDepositQueueHash = keccak256(abi.encode(DepositType.Regular, deposit, currentDepositQueueHash))`. The `Deposit` struct includes the `token` field. -3. The sequencer observes `DepositMade` events and processes deposits in order via `ZoneInbox.advanceTempo()`, minting the correct zone-side TIP-20 to the recipient: `IZoneToken(d.token).mint(d.to, d.amount)`. Deposits always succeed—there is no callback or bounce mechanism. -4. A batch proof/attestation must prove the zone correctly processed deposits by validating the Tempo state read inside the proof. -5. After the batch is accepted, `lastSyncedTempoBlockNumber` is updated to record how far Tempo state was synced. +1. User calls `ZonePortal.deposit(token, to, amount, memo, bouncebackRecipient)` on Tempo, specifying which enabled TIP-20 to deposit. The `bouncebackRecipient` is a Tempo L1 address that will receive refunded tokens if zone-side processing fails. +2. `ZonePortal` validates the token is enabled and deposits are active, validates that `bouncebackRecipient` is authorized under TIP-403 (see [Deposit bounce-back](#deposit-bounce-back-zone--tempo)), transfers `amount` of the specified token into escrow, and appends a deposit to the queue: `currentDepositQueueHash = keccak256(abi.encode(DepositType.Regular, deposit, currentDepositQueueHash))`. The `Deposit` struct includes the `token` and `bouncebackRecipient` fields. +3. The sequencer observes `DepositMade` events and processes deposits in order via `ZoneInbox.advanceTempo()`, minting the correct zone-side TIP-20 to the recipient: `IZoneToken(d.token).mint(d.to, d.amount)`. +4. If zone-side minting fails (e.g., zone-side TIP-403 policy blocks the recipient), the zone creates a **bounce-back withdrawal** that returns the funds to `bouncebackRecipient` on L1 (see [Deposit bounce-back](#deposit-bounce-back-zone--tempo)). +5. A batch proof/attestation must prove the zone correctly processed deposits (including any bouncebacks) by validating the Tempo state read inside the proof. +6. After the batch is accepted, `lastSyncedTempoBlockNumber` is updated to record how far Tempo state was synced. Notes: -- Deposits are simple token credits. There are no callbacks or failure modes on the zone side. +- Deposits that succeed are simple token credits with no callbacks. +- Deposits that fail on the zone side bounce back to `bouncebackRecipient` on L1. The sequencer processes the bounceback when submitting the next batch. - Deposits are finalized for Tempo once the batch is verified. - There is no forced inclusion. If the sequencer withholds deposits, funds are stuck in escrow. - The portal only stores `currentDepositQueueHash`, not individual deposits. The sequencer must track deposits off-chain. @@ -1570,52 +1583,153 @@ function processWithdrawal(Withdrawal calldata w, bytes32 remainingQueue) extern The messenger does `ITIP20(token).transferFrom(portal, target, amount)` then executes the callback. Both are atomic: if the callback reverts, the transferFrom reverts too, and funds remain in the portal for bounce-back. Receivers check `msg.sender == messenger` to authenticate the call, and receive the `senderTag` in `onWithdrawalReceived` (see [Authenticated withdrawals](#authenticated-withdrawals)). This enables composable withdrawals where funds can flow directly into Tempo contracts (e.g., DEX swaps, staking, cross-zone deposits). -## Withdrawal failure and bounce-back +## Bounce-back + +Bouncebacks provide a symmetric recovery mechanism for failed transfers in both directions. A withdrawal that fails on Tempo bounces back to the zone. A deposit that fails on the zone bounces back to Tempo. In both cases, the user's funds are never lost. + +### Withdrawal bounce-back (Tempo → zone) Withdrawals can fail if the token transfer or messenger callback reverts (out of gas, logic error, TIP-403 policy, token pause, etc.). When this happens, the portal "bounces back" the funds by re-depositing into the same zone to the withdrawal's `fallbackRecipient`. ```solidity -function _enqueueBounceBack(address token, uint128 amount, address fallbackRecipient) internal { +function _enqueueWithdrawalBounceBack(address token, uint128 amount, address fallbackRecipient) internal { Deposit memory d = Deposit({ - token: token, // same token from the failed withdrawal + token: token, sender: address(this), to: fallbackRecipient, amount: amount, - memo: bytes32(0) + memo: bytes32(0), + bouncebackRecipient: address(0) // bounce-back deposits do not themselves bounce }); currentDepositQueueHash = keccak256(abi.encode(DepositType.Regular, d, currentDepositQueueHash)); - emit BounceBack(...); + emit WithdrawalBounceBack(...); } ``` The zone processes bounce-back deposits and credits the `fallbackRecipient`. This allows withdrawals to fail gracefully without blocking the queue. +`fallbackRecipient` is a **zone address**. The user specifies it when requesting the withdrawal on the zone. It MUST NOT be `address(0)`. + +### Deposit bounce-back (zone → Tempo) + +Deposits can fail on the zone side if the mint is rejected (e.g., zone-side TIP-403 policy blocks the recipient, or decryption fails for encrypted deposits). When this happens, the zone enqueues a **bounce-back withdrawal** that returns the escrowed funds to the deposit's `bouncebackRecipient` on Tempo. + +```solidity +function _enqueueDepositBounceBack(address token, uint128 amount, address bouncebackRecipient) internal { + PendingWithdrawal memory w = PendingWithdrawal({ + token: token, + sender: address(0), // system-generated, no zone sender + txHash: bytes32(0), // no originating zone transaction + to: bouncebackRecipient, // L1 recipient (validated at deposit time) + amount: amount, + fee: 0, // no fee for bouncebacks + memo: bytes32(0), + gasLimit: 0, // simple transfer, no callback + fallbackRecipient: address(0), // N/A for deposit bouncebacks + callbackData: "", + revealTo: "" + }); + // Enqueue as a pending withdrawal for inclusion in the next batch + _enqueueBounceBackWithdrawal(w); + emit DepositBounceBack(token, bouncebackRecipient, amount); +} +``` + +**Zone-side processing**: During `advanceTempo()`, when a deposit fails: + +```solidity +// In ZoneInbox.advanceTempo(): +try IZoneToken(d.token).mint(d.to, d.amount) { + emit DepositProcessed(...); +} catch { + // Mint failed — bounce back to L1 + ZoneOutbox(_outbox)._enqueueDepositBounceBack(d.token, d.amount, d.bouncebackRecipient); + emit DepositFailed(currentHash, d.sender, d.to, d.token, d.amount, d.bouncebackRecipient); +} +``` + +The bounceback withdrawal is included in the zone's next withdrawal batch, and the portal processes it like any other withdrawal. The portal bypasses TIP-403 for bounceback transfers (see [Portal TIP-403 bypass](#portal-tip-403-bypass)). + +`bouncebackRecipient` is a **Tempo L1 address**. The user specifies it when making the deposit on L1. It MUST NOT be `address(0)`. + +### Deposit bounce-back for encrypted deposits + +Encrypted deposits already have a failure path when decryption fails: funds are minted to `ed.sender` on the zone. With deposit bouncebacks, a second failure path is added for when the decrypted recipient is rejected: + +1. **Decryption fails**: Funds are minted to `ed.sender` on the zone (existing behavior, unchanged). +2. **Decryption succeeds but mint fails**: Funds bounce back to `bouncebackRecipient` on L1 via a bounceback withdrawal. + +The `bouncebackRecipient` for encrypted deposits is set at deposit time, same as regular deposits. This ensures that even if the encrypted recipient turns out to be blacklisted, the depositor has a guaranteed recovery path. + +### Bounce-back properties + +| Property | Withdrawal bounce-back | Deposit bounce-back | +|----------|----------------------|-------------------| +| Direction | Tempo → zone | Zone → Tempo | +| Trigger | Transfer/callback fails on Tempo | Mint fails on zone | +| Recipient field | `fallbackRecipient` (zone address) | `bouncebackRecipient` (L1 address) | +| Validated at | Withdrawal request time (zone) | Deposit time (L1) | +| Fee | None (sequencer keeps original fee) | None (sequencer keeps original deposit fee) | +| Mechanism | Portal enqueues a deposit to zone | Zone enqueues a withdrawal to L1 | +| Recursive bouncing | No — bounce-back deposits have `bouncebackRecipient = address(0)` | No — bounce-back withdrawals have `fallbackRecipient = address(0)` | + +**No recursive bouncing**: Bounce-back deposits (from withdrawal failures) set `bouncebackRecipient = address(0)` and are guaranteed to succeed on the zone because they bypass all policy checks. Bounce-back withdrawals (from deposit failures) set `fallbackRecipient = address(0)` because TIP-403 is validated at deposit time and the portal bypasses TIP-403 for bounceback transfers. + +### Portal TIP-403 bypass + +The portal MUST be able to transfer tokens for bounceback withdrawals regardless of TIP-403 policy changes between deposit time and bounceback time. To achieve this: + +1. The portal contract address MUST be whitelisted as an authorized sender in the TIP-403 policy for every enabled token. +2. The `bouncebackRecipient` is validated against TIP-403 at deposit time. Even if the recipient is later blacklisted, the portal's whitelisted sender status ensures the transfer succeeds. +3. Alternatively, the TIP-20 contract can grant the portal a bypass role that exempts portal-initiated transfers from TIP-403 checks entirely. + +The choice between (2) and (3) depends on the TIP-403 implementation. Option (3) is more robust because it eliminates the race between deposit validation and bounceback execution. + +### Distinguishing bounce-back withdrawals + +The portal needs to distinguish bounce-back withdrawals from regular withdrawals to apply the correct TIP-403 treatment. Bounce-back withdrawals are identifiable by: + +- `fee == 0` (regular withdrawals always have a non-zero fee) +- `sender == address(0)` in the `PendingWithdrawal` struct +- `senderTag == bytes32(0)` in the finalized `Withdrawal` struct + +The portal SHOULD use these markers to skip TIP-403 recipient checks and apply the portal's bypass authorization when processing bounceback withdrawals. + ## Data availability and liveness - Zone data availability is fully trusted to the sequencer. - If the sequencer withholds data or halts, users cannot reconstruct zone state or force exits; batch posting and withdrawal processing are sequencer-only. - The design assumes users accept this risk in exchange for low-cost and fast settlement. -## Withdrawal failure details +## Failure details -Withdrawals can fail for various reasons. The system handles failures gracefully via bounce-back: - -### Failure reasons +### Withdrawal failures Withdrawals can fail due to: -- **Transfer failure**: `transfer` or `transferFrom` reverts (includes gasLimit = 0 cases) +- **Transfer failure**: `transfer` or `transferFrom` reverts - **TIP-403 policy**: Recipient not authorized under the token's transfer policy - **Token paused**: The token is globally paused - **Callback revert**: The receiver contract reverts (out of gas, logic error, etc.) - **Callback rejection**: Receiver returns wrong selector -### Withdrawal failures (Tempo-side) - When a withdrawal fails on Tempo: 1. The TIP-20 transfer or callback reverts 2. The portal enqueues a bounce-back deposit to `fallbackRecipient` on the zone 3. Funds return to zone via the normal deposit flow +### Deposit failures + +Deposits can fail on the zone due to: +- **Zone-side TIP-403 policy**: Recipient blocked by the zone's policy registry +- **Token misconfiguration**: Zone-side token predeploy rejects the mint +- **Encrypted deposit — decryption failure**: Chaum-Pedersen proof invalid or AES-GCM decryption fails (handled separately — mints to `sender` on zone) + +When a deposit fails on the zone: +1. The zone-side mint reverts +2. The zone enqueues a bounce-back withdrawal to `bouncebackRecipient` on L1 +3. The batch proof includes the bounceback withdrawal +4. The portal processes it and transfers escrowed funds to `bouncebackRecipient` + ### TIP-403 specific considerations Tempo TIP-20 tokens use TIP-403 for transfer authorization: @@ -1624,8 +1738,9 @@ Tempo TIP-20 tokens use TIP-403 for transfer authorization: - Policy ID 1 is "always-allow" (default for most tokens) Zone creators SHOULD choose tokens with `transferPolicyId == 1` to avoid complexity. If using restricted policies: -- The portal address MUST be whitelisted -- Users should set `fallbackRecipient` to an address they control +- The portal address MUST be whitelisted as an authorized sender +- Users should set `fallbackRecipient` / `bouncebackRecipient` to an address they control +- The portal MUST bypass TIP-403 for bounceback transfers (see [Portal TIP-403 bypass](#portal-tip-403-bypass)) ## Security considerations @@ -1633,9 +1748,9 @@ Zone creators SHOULD choose tokens with `transferPolicyId == 1` to avoid complex - The verifier is a trust anchor. A faulty verifier can steal or lock funds. - Withdrawals with callbacks go through the zone messenger with a user-specified gas limit. The messenger does `transferFrom` + callback atomically; any transfer or callback failure triggers a bounce-back to `fallbackRecipient`. - Deposits are locked on Tempo until a verified batch consumes them. -- **Bounce-back guarantees**: Failed withdrawals bounce back to zone `fallbackRecipient`. Users always retain their funds. -- **TIP-403 policy changes**: If a token's policy restricts the portal, withdrawals for that token will fail and bounce back. -- **Token pause**: If a token is paused, withdrawals for that token bounce back to zone. +- **Bounce-back guarantees**: Failed withdrawals bounce back to zone `fallbackRecipient`. Failed deposits bounce back to L1 `bouncebackRecipient`. Users always retain their funds in both directions. +- **TIP-403 policy changes**: If a token's policy restricts the portal or a recipient, transfers fail and bounce back. The portal bypasses TIP-403 for bounceback transfers to ensure funds are always recoverable. +- **Token pause**: If a token is paused, withdrawals for that token bounce back to zone. Deposits that fail zone-side bounce back to L1. ## Implementation architecture diff --git a/docs/pages/protocol/privacy/rpc.md b/docs/pages/protocol/privacy/rpc.md index 4ad5f671a..0fd42b0b2 100644 --- a/docs/pages/protocol/privacy/rpc.md +++ b/docs/pages/protocol/privacy/rpc.md @@ -28,8 +28,9 @@ The signed message is the `keccak256` hash of the following packed encoding: bytes32 authorizationTokenHash = keccak256(abi.encodePacked( bytes32(0x54656d706f5a6f6e65525043), // "TempoZoneRPC" magic prefix uint8(version), // spec version (currently 0) - uint32(zoneId), // zone this key is valid for (0 = unscoped) + uint32(zoneId), // zone this key is valid for uint64(chainId), // zone chain ID (replay protection) + address(zonePortal), // ZonePortal address on Tempo uint64(issuedAt), // unix timestamp (seconds) of issuance uint64(expiresAt) // unix timestamp (seconds) of expiry )); @@ -39,14 +40,6 @@ The `version` field MUST be `0` for this version of the spec. The RPC server MUS This hash is the challenge that must be signed. Using a raw `keccak256` hash (rather than EIP-191 personal messages or EIP-712 typed data) allows all Tempo signature types to sign the same message consistently — P256 and WebAuthn signers cannot produce EIP-191 prefixed signatures. The `"TempoZoneRPC"` magic prefix provides domain separation, ensuring that authorization token hashes cannot collide with Tempo transaction hashes or other signing contexts. -### Unscoped tokens - -A `zoneId` of `0` indicates an **unscoped** authorization token that is valid for any zone. Zone IDs are assigned by `ZoneFactory` starting at 1, so `0` is never a valid zone ID. - -When the RPC server receives a token with `zoneId == 0`, it MUST skip the zone ID check and accept the token for any zone. All other validation rules (version, chain ID, expiry, signature) still apply. The `chainId` field continues to provide cross-network replay protection. - -Unscoped tokens are useful for applications and SDKs that interact with multiple zones on the same network without managing separate tokens per zone. Since authorization tokens are read-only credentials (no RPC method authenticated solely by a token may modify state), the additional exposure is limited to read access across zones the user has accounts in. - ### Signature types The authorization token signature follows the same format as [Tempo transaction signatures](/protocol/transactions/spec-tempo-transaction#signature-types). The signature type is determined by the first byte and length: @@ -116,9 +109,10 @@ This allows session keys and scoped Access Keys to authenticate to the RPC with The RPC server MUST reject authorization tokens where: -- `zoneId` does not equal the zone's configured `zoneId` **and** `zoneId` is not `0` (an unscoped token with `zoneId == 0` is valid for any zone — see [Unscoped tokens](#unscoped-tokens)). +- `zoneId` does not equal the zone's configured `zoneId`. - `chainId` does not equal the zone's configured chain ID (`eth_chainId`). -- `expiresAt - issuedAt > 2592000` (maximum validity window is 30 days). +- `zonePortal` does not equal the zone's configured Tempo ZonePortal address. +- `expiresAt - issuedAt > 1800` (maximum validity window is 30 minutes). - `expiresAt <= now` (key has expired). - `issuedAt > now + 60` (clock skew tolerance of 60 seconds into the future). - The signature is malformed or does not verify. @@ -143,10 +137,10 @@ Content-Type: application/json The `X-Authorization-Token` value is a single hex-encoded blob containing the concatenation of the signature and the authorization token fields: ``` - + ``` -The authorization token fields are always exactly 29 bytes (1 + 4 + 8 + 8 + 8). To parse the blob, the RPC server reads the **last 29 bytes** as the authorization token fields, and treats everything before them as the signature. The signature is then parsed using the same detection rules as [Tempo transaction signatures](/protocol/transactions/spec-tempo-transaction#signature-types) (secp256k1 is exactly 65 bytes; P256 starts with `0x01` and is 130 bytes; WebAuthn starts with `0x02` and is variable-length; Keychain starts with `0x03` for legacy V1 or `0x04` for V2 and is variable-length). Parsing from the end avoids any ambiguity with variable-length signature types. +The authorization token fields are always exactly 49 bytes (1 + 4 + 8 + 20 + 8 + 8). To parse the blob, the RPC server reads the **last 49 bytes** as the authorization token fields, and treats everything before them as the signature. The signature is then parsed using the same detection rules as [Tempo transaction signatures](/protocol/transactions/spec-tempo-transaction#signature-types) (secp256k1 is exactly 65 bytes; P256 starts with `0x01` and is 130 bytes; WebAuthn starts with `0x02` and is variable-length; Keychain starts with `0x03` for legacy V1 or `0x04` for V2 and is variable-length). Parsing from the end avoids any ambiguity with variable-length signature types. Requests without an authorization token receive a `401 Unauthorized` HTTP response. Requests with an expired, malformed, or unauthorized token receive `403 Forbidden`. If Keychain token verification fails because the server cannot read `AccountKeychain.getKey(...)`, the server returns `500 Internal Server Error`. @@ -491,7 +485,7 @@ In addition to standard JSON-RPC error codes, the zone RPC uses: - **Side channels via timing**: Scoped methods that must fetch data before checking authorization are subject to a mandatory 100 ms response floor (see [Timing side channels and the 100 ms speed bump](#timing-side-channels-and-the-100-ms-speed-bump)). This ensures that `eth_getTransactionByHash` for a non-existent transaction and for another user's transaction have indistinguishable response times. - **Nonce privacy**: `eth_getTransactionCount` for non-authenticated accounts returns `0x0` rather than an error. This avoids revealing whether an account exists. The constant `0x0` response is indistinguishable from a genuinely new account. -- **Authorization token replay**: Authorization tokens are scoped to a specific zone (`zoneId`) and network (`chainId`), with a maximum 30-day validity window. When `zoneId` is `0` (unscoped), the token is valid across all zones on that network. Authorization tokens are strictly read-only credentials — no RPC method that is authenticated solely by an authorization token may modify state (see [Withdrawals](#zone-specific-rpc-methods)). The RPC server SHOULD implement nonce tracking or rate limiting to further reduce the window for abuse if a token is intercepted, but replay of a read-only token cannot move funds. +- **Authorization token replay**: Authorization tokens are scoped to a specific zone (`zoneId` and `chainId`) and a specific portal (`zonePortal`), with a maximum 30-minute window. Authorization tokens are strictly read-only credentials — no RPC method that is authenticated solely by an authorization token may modify state (see [Withdrawals](#zone-specific-rpc-methods)). The RPC server SHOULD implement nonce tracking or rate limiting to further reduce the window for abuse if a token is intercepted, but replay of a read-only token cannot move funds. - **Simulation override extensions**: Some Ethereum clients support non-standard simulation extensions (state override sets and block override objects) on `eth_call`/`eth_estimateGas`. Privacy zones MUST reject these extensions for non-sequencer callers, because they can bypass or distort normal state access assumptions used by this spec's privacy model. - **Keychain key revocation and expiry**: When a root account revokes a Keychain key on-chain, the RPC server MUST stop accepting that key within 1 second of importing the block that contains the revocation. Cached Keychain verifications MUST also honor key expiry: a cache entry MUST expire no later than `min(authorizationToken.expiresAt, keyExpiry)` where `keyExpiry` is read from `AccountKeychain.getKey(...)`. In the current `AccountKeychain` implementation, inactive or revoked keys are surfaced as `keyId == 0` and `expiry == 0`, so those results MUST be treated as immediately invalid rather than "never expires." The recommended implementation is event-driven: the zone node watches for `KeyRevoked(account, publicKey)` events emitted by the AccountKeychain precompile during block execution and immediately evicts matching entries from the authorization token cache. This requires no cryptography — just a cache lookup and delete. As a fallback, implementations MAY poll the precompile via `getKey(user_address, keyId)`, but the 1-second deadline still applies. - **P256/WebAuthn key compromise**: Unlike secp256k1, P256 and WebAuthn keys include the public key in the signature. This means the public key is visible to the RPC server on every request. This is not a security concern (public keys are public), but implementations should be aware that the key material is transmitted in the clear over the connection. diff --git a/docs/specs/src/zone/IZone.sol b/docs/specs/src/zone/IZone.sol index 5586bbaaa..1ebf5c504 100644 --- a/docs/specs/src/zone/IZone.sol +++ b/docs/specs/src/zone/IZone.sol @@ -63,6 +63,7 @@ struct Deposit { address to; uint128 amount; bytes32 memo; + address bouncebackRecipient; // L1 address for refund if zone-side processing fails (address(0) for bounce-back deposits) } /*////////////////////////////////////////////////////////////// @@ -90,6 +91,7 @@ struct EncryptedDeposit { uint128 amount; // Amount (public, for accounting) uint256 keyIndex; // Index of encryption key used (specified by depositor) EncryptedDepositPayload encrypted; // Encrypted (to, memo) + address bouncebackRecipient; // L1 address for refund if zone-side processing fails } /// @notice Historical record of an encryption key with its activation block @@ -472,7 +474,8 @@ interface IZonePortal { address to, uint128 netAmount, uint128 fee, - bytes32 memo + bytes32 memo, + address bouncebackRecipient ); event BatchSubmitted( @@ -486,13 +489,15 @@ interface IZonePortal { address indexed to, address token, uint128 amount, bool callbackSuccess ); - event BounceBack( + event WithdrawalBounceBack( bytes32 indexed newCurrentDepositQueueHash, address indexed fallbackRecipient, address token, uint128 amount ); + event DepositBounceBack(address indexed bouncebackRecipient, address token, uint128 amount); + event SequencerTransferStarted( address indexed currentSequencer, address indexed pendingSequencer ); @@ -674,7 +679,8 @@ interface IZonePortal { address token, address to, uint128 amount, - bytes32 memo + bytes32 memo, + address bouncebackRecipient ) external returns (bytes32 newCurrentDepositQueueHash); @@ -688,12 +694,14 @@ interface IZonePortal { /// @param amount Amount to deposit /// @param keyIndex Index of the encryption key used (from encryptionKeyAt) /// @param encrypted The encrypted payload (recipient and memo) + /// @param bouncebackRecipient L1 address for refund if zone-side processing fails /// @return newCurrentDepositQueueHash The new deposit queue hash function depositEncrypted( address token, uint128 amount, uint256 keyIndex, - EncryptedDepositPayload calldata encrypted + EncryptedDepositPayload calldata encrypted, + address bouncebackRecipient ) external returns (bytes32 newCurrentDepositQueueHash); @@ -854,6 +862,17 @@ interface IZoneInbox { event EncryptedDepositFailed( bytes32 indexed depositHash, address indexed sender, address token, uint128 amount ); + + /// @notice Emitted when a regular deposit fails zone-side (e.g., TIP-403 blocks the mint) + event DepositFailed( + bytes32 indexed depositHash, + address indexed sender, + address to, + address token, + uint128 amount, + address bouncebackRecipient + ); + /// @notice Emitted when a TIP-20 token is enabled on the zone via advanceTempo event TokenEnabled(address indexed token, string name, string symbol, string currency); @@ -998,6 +1017,17 @@ interface IZoneOutbox { external returns (bytes32 withdrawalQueueHash); + /// @notice Enqueue a bounce-back withdrawal for a failed deposit + /// @dev Only callable by the ZoneInbox during advanceTempo when a deposit mint fails. + /// The bounce-back withdrawal returns escrowed funds to the depositor's + /// bouncebackRecipient on L1. + function enqueueDepositBounceBack( + address token, + uint128 amount, + address bouncebackRecipient + ) + external; + } /// @title IZoneConfig diff --git a/docs/specs/src/zone/SwapAndDepositRouter.sol b/docs/specs/src/zone/SwapAndDepositRouter.sol index 94c3c17fb..ac6dd81ad 100644 --- a/docs/specs/src/zone/SwapAndDepositRouter.sol +++ b/docs/specs/src/zone/SwapAndDepositRouter.sol @@ -91,7 +91,8 @@ contract SwapAndDepositRouter is IWithdrawalReceiver { uint128 amountOut = _swapIfNeeded(tokenIn, tokenOut, amount, minAmountOut); IERC20(tokenOut).approve(targetPortal, amountOut); - IZonePortal(targetPortal).depositEncrypted(tokenOut, amountOut, keyIndex, encrypted); + IZonePortal(targetPortal) + .depositEncrypted(tokenOut, amountOut, keyIndex, encrypted, msg.sender); } else { (, // skip isEncrypted address tokenOut, @@ -106,7 +107,7 @@ contract SwapAndDepositRouter is IWithdrawalReceiver { uint128 amountOut = _swapIfNeeded(tokenIn, tokenOut, amount, minAmountOut); IERC20(tokenOut).approve(targetPortal, amountOut); - IZonePortal(targetPortal).deposit(tokenOut, recipient, amountOut, memo); + IZonePortal(targetPortal).deposit(tokenOut, recipient, amountOut, memo, msg.sender); } return IWithdrawalReceiver.onWithdrawalReceived.selector; diff --git a/docs/specs/src/zone/ZoneInbox.sol b/docs/specs/src/zone/ZoneInbox.sol index 98839f85f..d1c0a109d 100644 --- a/docs/specs/src/zone/ZoneInbox.sol +++ b/docs/specs/src/zone/ZoneInbox.sol @@ -16,6 +16,7 @@ import { ITempoState, IZoneConfig, IZoneInbox, + IZoneOutbox, IZoneToken, PORTAL_CURRENT_DEPOSIT_QUEUE_HASH_SLOT, PORTAL_ENCRYPTION_KEYS_SLOT, @@ -43,6 +44,9 @@ contract ZoneInbox is IZoneInbox { /// @notice The TempoState predeploy address (stored as concrete type for internal use) TempoState internal immutable _tempoState; + /// @notice The ZoneOutbox predeploy (for enqueuing deposit bouncebacks) + IZoneOutbox public immutable outbox; + /// @notice Last processed deposit queue hash (validated against Tempo state) bytes32 public processedDepositQueueHash; @@ -50,10 +54,16 @@ contract ZoneInbox is IZoneInbox { CONSTRUCTOR //////////////////////////////////////////////////////////////*/ - constructor(address _config, address _tempoPortalAddr, address _tempoStateAddr) { + constructor( + address _config, + address _tempoPortalAddr, + address _tempoStateAddr, + address _outbox + ) { config = IZoneConfig(_config); tempoPortal = _tempoPortalAddr; _tempoState = TempoState(_tempoStateAddr); + outbox = IZoneOutbox(_outbox); } /// @notice The TempoState predeploy address @@ -207,10 +217,23 @@ contract ZoneInbox is IZoneInbox { // Advance the hash chain with type discriminator currentHash = keccak256(abi.encode(DepositType.Regular, d, currentHash)); - // Mint the correct zone-side TIP-20 token to the recipient - IZoneToken(d.token).mint(d.to, d.amount); - - emit DepositProcessed(currentHash, d.sender, d.to, d.token, d.amount, d.memo); + if (d.bouncebackRecipient != address(0)) { + // Normal deposit: try minting, bounce back on failure + try IZoneToken(d.token).mint(d.to, d.amount) { + emit DepositProcessed( + currentHash, d.sender, d.to, d.token, d.amount, d.memo + ); + } catch { + outbox.enqueueDepositBounceBack(d.token, d.amount, d.bouncebackRecipient); + emit DepositFailed( + currentHash, d.sender, d.to, d.token, d.amount, d.bouncebackRecipient + ); + } + } else { + // Bounce-back deposit from a failed withdrawal — always succeeds + IZoneToken(d.token).mint(d.to, d.amount); + emit DepositProcessed(currentHash, d.sender, d.to, d.token, d.amount, d.memo); + } } else { // Decode encrypted deposit EncryptedDeposit memory ed = abi.decode(qd.depositData, (EncryptedDeposit)); @@ -272,16 +295,46 @@ contract ZoneInbox is IZoneInbox { currentHash = keccak256(abi.encode(DepositType.Encrypted, ed, currentHash)); if (!valid) { - // Decryption failed: credit the depositor's address on the zone. - // L1 funds remain escrowed in the portal. - IZoneToken(ed.token).mint(ed.sender, ed.amount); - emit EncryptedDepositFailed(currentHash, ed.sender, ed.token, ed.amount); + // Decryption failed: try crediting the depositor's address on the zone. + if (ed.bouncebackRecipient != address(0)) { + try IZoneToken(ed.token).mint(ed.sender, ed.amount) { + emit EncryptedDepositFailed(currentHash, ed.sender, ed.token, ed.amount); + } catch { + outbox.enqueueDepositBounceBack( + ed.token, ed.amount, ed.bouncebackRecipient + ); + emit EncryptedDepositFailed(currentHash, ed.sender, ed.token, ed.amount); + } + } else { + IZoneToken(ed.token).mint(ed.sender, ed.amount); + emit EncryptedDepositFailed(currentHash, ed.sender, ed.token, ed.amount); + } } else { - // Decryption succeeded - mint the correct zone-side TIP-20 to the decrypted recipient - IZoneToken(ed.token).mint(dec.to, ed.amount); - emit EncryptedDepositProcessed( - currentHash, ed.sender, dec.to, ed.token, ed.amount, dec.memo - ); + // Decryption succeeded: try minting to the decrypted recipient + if (ed.bouncebackRecipient != address(0)) { + try IZoneToken(ed.token).mint(dec.to, ed.amount) { + emit EncryptedDepositProcessed( + currentHash, ed.sender, dec.to, ed.token, ed.amount, dec.memo + ); + } catch { + outbox.enqueueDepositBounceBack( + ed.token, ed.amount, ed.bouncebackRecipient + ); + emit DepositFailed( + currentHash, + ed.sender, + dec.to, + ed.token, + ed.amount, + ed.bouncebackRecipient + ); + } + } else { + IZoneToken(ed.token).mint(dec.to, ed.amount); + emit EncryptedDepositProcessed( + currentHash, ed.sender, dec.to, ed.token, ed.amount, dec.memo + ); + } } } } diff --git a/docs/specs/src/zone/ZoneOutbox.sol b/docs/specs/src/zone/ZoneOutbox.sol index b3ccb19c2..6df45fd13 100644 --- a/docs/specs/src/zone/ZoneOutbox.sol +++ b/docs/specs/src/zone/ZoneOutbox.sol @@ -400,6 +400,36 @@ contract ZoneOutbox is IZoneOutbox { emit BatchFinalized(withdrawalQueueHash, currentWithdrawalBatchIndex); } + /// @notice Enqueue a bounce-back withdrawal for a failed deposit + /// @dev Only callable by the ZoneInbox during advanceTempo. Creates a zero-fee, + /// zero-callback withdrawal that returns escrowed funds to the depositor's + /// bouncebackRecipient on L1. + function enqueueDepositBounceBack( + address token, + uint128 amount, + address bouncebackRecipient + ) + external + { + if (msg.sender != address(0) && msg.sender != config.sequencer()) revert OnlySequencer(); + + _pendingWithdrawals.push( + PendingWithdrawal({ + token: token, + sender: address(0), + txHash: bytes32(0), + to: bouncebackRecipient, + amount: amount, + fee: 0, + memo: bytes32(0), + gasLimit: 0, + fallbackRecipient: address(0), + callbackData: "", + revealTo: "" + }) + ); + } + /// @notice Number of pending withdrawals function pendingWithdrawalsCount() external view returns (uint256) { if (_pendingWithdrawalsHead >= _pendingWithdrawals.length) { diff --git a/docs/specs/src/zone/ZonePortal.sol b/docs/specs/src/zone/ZonePortal.sol index bf02c5414..9eb3596c9 100644 --- a/docs/specs/src/zone/ZonePortal.sol +++ b/docs/specs/src/zone/ZonePortal.sol @@ -467,7 +467,8 @@ contract ZonePortal is IZonePortal { address _token, address to, uint128 amount, - bytes32 memo + bytes32 memo, + address bouncebackRecipient ) external returns (bytes32 newCurrentDepositQueueHash) @@ -487,6 +488,15 @@ contract ZonePortal is IZonePortal { revert DepositPolicyForbids(); } + // Validate bouncebackRecipient against TIP-403 at deposit time so that + // bounceback transfers on L1 are guaranteed to succeed even if the + // recipient is later blacklisted (portal has a TIP-403 bypass). + if (bouncebackRecipient != address(0)) { + if (!TIP403_REGISTRY.isAuthorizedRecipient(policyId, bouncebackRecipient)) { + revert DepositPolicyForbids(); + } + } + // Calculate deposit fee uint128 fee = calculateDepositFee(); if (amount <= fee) revert DepositTooSmall(); @@ -502,14 +512,29 @@ contract ZonePortal is IZonePortal { } // Build deposit struct with net amount (fee already paid to sequencer on Tempo) - Deposit memory depositData = - Deposit({ token: _token, sender: msg.sender, to: to, amount: netAmount, memo: memo }); + Deposit memory depositData = Deposit({ + token: _token, + sender: msg.sender, + to: to, + amount: netAmount, + memo: memo, + bouncebackRecipient: bouncebackRecipient + }); // Insert deposit into queue newCurrentDepositQueueHash = DepositQueueLib.enqueue(currentDepositQueueHash, depositData); currentDepositQueueHash = newCurrentDepositQueueHash; - emit DepositMade(newCurrentDepositQueueHash, msg.sender, _token, to, netAmount, fee, memo); + emit DepositMade( + newCurrentDepositQueueHash, + msg.sender, + _token, + to, + netAmount, + fee, + memo, + bouncebackRecipient + ); } /// @notice Deposit with encrypted recipient and memo @@ -526,7 +551,8 @@ contract ZonePortal is IZonePortal { address _token, uint128 amount, uint256 keyIndex, - EncryptedDepositPayload calldata encrypted + EncryptedDepositPayload calldata encrypted, + address bouncebackRecipient ) external returns (bytes32 newCurrentDepositQueueHash) @@ -579,7 +605,8 @@ contract ZonePortal is IZonePortal { sender: msg.sender, amount: netAmount, keyIndex: keyIndex, - encrypted: encrypted + encrypted: encrypted, + bouncebackRecipient: bouncebackRecipient }); // Insert encrypted deposit into queue @@ -638,7 +665,9 @@ contract ZonePortal is IZonePortal { } if (!success) { - _enqueueBounceBack(_token, withdrawal.amount, withdrawal.fallbackRecipient); + _enqueueWithdrawalBounceBack( + _token, withdrawal.amount, withdrawal.fallbackRecipient + ); emit WithdrawalProcessed(withdrawal.to, _token, withdrawal.amount, false); return; } @@ -660,16 +689,16 @@ contract ZonePortal is IZonePortal { emit WithdrawalProcessed(withdrawal.to, _token, withdrawal.amount, true); } catch { // Callback failed: bounce back to zone (only amount, not fee) - _enqueueBounceBack(_token, withdrawal.amount, withdrawal.fallbackRecipient); + _enqueueWithdrawalBounceBack(_token, withdrawal.amount, withdrawal.fallbackRecipient); emit WithdrawalProcessed(withdrawal.to, _token, withdrawal.amount, false); } } - /// @notice Enqueue a bounce-back deposit for failed callback + /// @notice Enqueue a bounce-back deposit for a failed withdrawal callback /// @param _token The token from the failed withdrawal /// @param amount The amount to bounce back /// @param fallbackRecipient The zone address to receive the bounce-back - function _enqueueBounceBack( + function _enqueueWithdrawalBounceBack( address _token, uint128 amount, address fallbackRecipient @@ -681,14 +710,15 @@ contract ZonePortal is IZonePortal { sender: address(this), to: fallbackRecipient, amount: amount, - memo: bytes32(0) + memo: bytes32(0), + bouncebackRecipient: address(0) }); bytes32 newCurrentDepositQueueHash = DepositQueueLib.enqueue(currentDepositQueueHash, depositData); currentDepositQueueHash = newCurrentDepositQueueHash; - emit BounceBack(newCurrentDepositQueueHash, fallbackRecipient, _token, amount); + emit WithdrawalBounceBack(newCurrentDepositQueueHash, fallbackRecipient, _token, amount); } /*////////////////////////////////////////////////////////////// diff --git a/docs/specs/test/zone/DepositQueueLib.t.sol b/docs/specs/test/zone/DepositQueueLib.t.sol index 12f1d2207..ca34782ba 100644 --- a/docs/specs/test/zone/DepositQueueLib.t.sol +++ b/docs/specs/test/zone/DepositQueueLib.t.sol @@ -40,7 +40,8 @@ contract DepositQueueLibTest is Test { sender: address(0x200), to: address(0x300), amount: 100e6, - memo: bytes32("memo") + memo: bytes32("memo"), + bouncebackRecipient: address(0) }); bytes32 newHash = DepositQueueLib.enqueue(bytes32(0), d); @@ -55,21 +56,24 @@ contract DepositQueueLibTest is Test { sender: address(0x200), to: address(0x300), amount: 100e6, - memo: bytes32("d1") + memo: bytes32("d1"), + bouncebackRecipient: address(0) }); Deposit memory d2 = Deposit({ token: address(0x1000), sender: address(0x300), to: address(0x200), amount: 200e6, - memo: bytes32("d2") + memo: bytes32("d2"), + bouncebackRecipient: address(0) }); Deposit memory d3 = Deposit({ token: address(0x1000), sender: address(0x200), to: address(0x200), amount: 300e6, - memo: bytes32("d3") + memo: bytes32("d3"), + bouncebackRecipient: address(0) }); bytes32 h1 = DepositQueueLib.enqueue(bytes32(0), d1); @@ -93,14 +97,16 @@ contract DepositQueueLibTest is Test { sender: address(0x200), to: address(0x300), amount: 100e6, - memo: bytes32("first") + memo: bytes32("first"), + bouncebackRecipient: address(0) }); Deposit memory d2 = Deposit({ token: address(0x1000), sender: address(0x300), to: address(0x200), amount: 200e6, - memo: bytes32("second") + memo: bytes32("second"), + bouncebackRecipient: address(0) }); bytes32 h1 = DepositQueueLib.enqueue(bytes32(0), d1); @@ -113,7 +119,12 @@ contract DepositQueueLibTest is Test { function test_enqueue_emptyToEmpty() public pure { // An empty deposit struct should still produce a valid hash Deposit memory d = Deposit({ - token: address(0x1000), sender: address(0), to: address(0), amount: 0, memo: bytes32(0) + token: address(0x1000), + sender: address(0), + to: address(0), + amount: 0, + memo: bytes32(0), + bouncebackRecipient: address(0) }); bytes32 h = DepositQueueLib.enqueue(bytes32(0), d); @@ -128,14 +139,16 @@ contract DepositQueueLibTest is Test { sender: address(0x200), to: address(0x300), amount: 100e6, - memo: bytes32("memo1") + memo: bytes32("memo1"), + bouncebackRecipient: address(0) }); Deposit memory d2 = Deposit({ token: address(0x1000), sender: address(0x200), to: address(0x300), amount: 100e6, - memo: bytes32("memo2") // Only memo differs + memo: bytes32("memo2"), // Only memo differs + bouncebackRecipient: address(0) }); bytes32 h1 = DepositQueueLib.enqueue(bytes32(0), d1); @@ -150,7 +163,8 @@ contract DepositQueueLibTest is Test { sender: address(0x200), to: address(0x300), amount: 100e6, - memo: bytes32("memo") + memo: bytes32("memo"), + bouncebackRecipient: address(0) }); bytes32 h1 = DepositQueueLib.enqueue(bytes32(0), d); @@ -175,7 +189,8 @@ contract DepositQueueLibTest is Test { ciphertext: new bytes(64), nonce: bytes12(0), tag: bytes16(0) - }) + }), + bouncebackRecipient: address(0) }); bytes32 newHash = DepositQueueLib.enqueueEncrypted(bytes32(0), ed); @@ -189,7 +204,8 @@ contract DepositQueueLibTest is Test { sender: address(0x200), to: address(0x300), amount: 100e6, - memo: bytes32("d1") + memo: bytes32("d1"), + bouncebackRecipient: address(0) }); EncryptedDeposit memory ed = EncryptedDeposit({ @@ -203,7 +219,8 @@ contract DepositQueueLibTest is Test { ciphertext: new bytes(64), nonce: bytes12(0), tag: bytes16(0) - }) + }), + bouncebackRecipient: address(0) }); Deposit memory d2 = Deposit({ @@ -211,7 +228,8 @@ contract DepositQueueLibTest is Test { sender: address(0x200), to: address(0x200), amount: 300e6, - memo: bytes32("d3") + memo: bytes32("d3"), + bouncebackRecipient: address(0) }); bytes32 h1 = DepositQueueLib.enqueue(bytes32(0), d1); @@ -234,7 +252,8 @@ contract DepositQueueLibTest is Test { sender: address(0x200), to: address(0x300), amount: 100e6, - memo: bytes32("memo") + memo: bytes32("memo"), + bouncebackRecipient: address(0) }); EncryptedDeposit memory ed = EncryptedDeposit({ @@ -248,7 +267,8 @@ contract DepositQueueLibTest is Test { ciphertext: "", nonce: bytes12(0), tag: bytes16(0) - }) + }), + bouncebackRecipient: address(0) }); bytes32 regularHash = DepositQueueLib.enqueue(bytes32(0), d); diff --git a/docs/specs/test/zone/SwapAndDepositRouter.t.sol b/docs/specs/test/zone/SwapAndDepositRouter.t.sol index 1108d2893..0d01c2cb6 100644 --- a/docs/specs/test/zone/SwapAndDepositRouter.t.sol +++ b/docs/specs/test/zone/SwapAndDepositRouter.t.sol @@ -96,7 +96,8 @@ contract MockZonePortalForRouter { address _token, address to, uint128 amount, - bytes32 memo + bytes32 memo, + address /* bouncebackRecipient */ ) external returns (bytes32) @@ -113,7 +114,8 @@ contract MockZonePortalForRouter { address _token, uint128 amount, uint256 keyIndex, - EncryptedDepositPayload calldata + EncryptedDepositPayload calldata, + address /* bouncebackRecipient */ ) external returns (bytes32) diff --git a/docs/specs/test/zone/ZoneBridge.t.sol b/docs/specs/test/zone/ZoneBridge.t.sol index 7fe5506ff..f95fef6ad 100644 --- a/docs/specs/test/zone/ZoneBridge.t.sol +++ b/docs/specs/test/zone/ZoneBridge.t.sol @@ -172,7 +172,8 @@ contract ZoneBridgeTest is BaseTest { ); // Zone inbox (advances Tempo state and processes deposits) - l2Inbox = new ZoneInbox(address(l2Config), address(l1Portal), address(l2TempoState)); + l2Inbox = + new ZoneInbox(address(l2Config), address(l1Portal), address(l2TempoState), address(0)); l2ZoneToken.setMinter(address(l2Inbox), true); // Zone outbox (handles withdrawals) @@ -252,7 +253,12 @@ contract ZoneBridgeTest is BaseTest { { // Record the deposit Deposit memory d = Deposit({ - token: address(l2ZoneToken), sender: sender, to: to, amount: amount, memo: memo + token: address(l2ZoneToken), + sender: sender, + to: to, + amount: amount, + memo: memo, + bouncebackRecipient: address(0) }); // Calculate the new hash (matches what Tempo portal computes) @@ -393,8 +399,9 @@ contract ZoneBridgeTest is BaseTest { uint128 depositAmount = 1000e6; vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), depositAmount); - bytes32 l1DepositHash = - l1Portal.deposit(address(l2ZoneToken), alice, depositAmount, bytes32("hello zone")); + bytes32 l1DepositHash = l1Portal.deposit( + address(l2ZoneToken), alice, depositAmount, bytes32("hello zone"), address(0) + ); vm.stopPrank(); // Verify L1 state @@ -470,12 +477,12 @@ contract ZoneBridgeTest is BaseTest { // === Alice and Bob both deposit === vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), 5000e6); - l1Portal.deposit(address(l2ZoneToken), alice, 2000e6, bytes32("alice1")); + l1Portal.deposit(address(l2ZoneToken), alice, 2000e6, bytes32("alice1"), address(0)); vm.stopPrank(); vm.startPrank(bob); l2ZoneToken.approve(address(l1Portal), 5000e6); - l1Portal.deposit(address(l2ZoneToken), bob, 3000e6, bytes32("bob1")); + l1Portal.deposit(address(l2ZoneToken), bob, 3000e6, bytes32("bob1"), address(0)); vm.stopPrank(); // Sequencer observes and relays @@ -532,7 +539,7 @@ contract ZoneBridgeTest is BaseTest { // Setup: deposit to zone vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), 1000e6); - l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32("")); + l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32(""), address(0)); vm.stopPrank(); _sequencerObserveDeposit(alice, alice, 1000e6, bytes32("")); @@ -591,7 +598,7 @@ contract ZoneBridgeTest is BaseTest { // Setup: deposit to zone vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), 1000e6); - l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32("")); + l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32(""), address(0)); vm.stopPrank(); _sequencerObserveDeposit(alice, alice, 1000e6, bytes32("")); @@ -639,7 +646,7 @@ contract ZoneBridgeTest is BaseTest { // Deposit to Alice vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), 1000e6); - l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32("")); + l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32(""), address(0)); vm.stopPrank(); _sequencerObserveDeposit(alice, alice, 1000e6, bytes32("")); @@ -668,7 +675,7 @@ contract ZoneBridgeTest is BaseTest { // Deposit to Alice vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), 1000e6); - l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32("")); + l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32(""), address(0)); vm.stopPrank(); _sequencerObserveDeposit(alice, alice, 1000e6, bytes32("")); @@ -688,7 +695,7 @@ contract ZoneBridgeTest is BaseTest { // Deposit to Alice vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), 1000e6); - l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32("")); + l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32(""), address(0)); vm.stopPrank(); _sequencerObserveDeposit(alice, alice, 1000e6, bytes32("")); @@ -704,7 +711,7 @@ contract ZoneBridgeTest is BaseTest { // Deposit on L1 vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), 1000e6); - l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32("")); + l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32(""), address(0)); vm.stopPrank(); _sequencerObserveDeposit(alice, alice, 1000e6, bytes32("")); @@ -728,7 +735,7 @@ contract ZoneBridgeTest is BaseTest { // Deposit to Alice vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), 1000e6); - l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32("")); + l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32(""), address(0)); vm.stopPrank(); _sequencerObserveDeposit(alice, alice, 1000e6, bytes32("")); @@ -753,7 +760,7 @@ contract ZoneBridgeTest is BaseTest { function test_l2_onlySequencerCanAdvanceTempo() public { vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), 1000e6); - l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32("")); + l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32(""), address(0)); vm.stopPrank(); _sequencerObserveDeposit(alice, alice, 1000e6, bytes32("")); @@ -785,7 +792,7 @@ contract ZoneBridgeTest is BaseTest { // Make a deposit to get a non-zero currentDepositQueueHash vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), 1000e6); - l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32("layout-test")); + l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32("layout-test"), address(0)); vm.stopPrank(); // Read via vm.load using our constant @@ -859,7 +866,8 @@ contract ZoneBridgeTest is BaseTest { sender: sender, amount: netAmount, keyIndex: keyIndex, - encrypted: encrypted + encrypted: encrypted, + bouncebackRecipient: address(0) }); // Calculate the new hash (matches what portal computes via DepositQueueLib) @@ -1015,7 +1023,7 @@ contract ZoneBridgeTest is BaseTest { vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), depositAmount); bytes32 l1DepositHash = - l1Portal.depositEncrypted(address(l2ZoneToken), depositAmount, 0, payload); + l1Portal.depositEncrypted(address(l2ZoneToken), depositAmount, 0, payload, address(0)); vm.stopPrank(); // Verify L1 state @@ -1080,7 +1088,7 @@ contract ZoneBridgeTest is BaseTest { vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), depositAmount); - l1Portal.depositEncrypted(address(l2ZoneToken), depositAmount, 0, payload); + l1Portal.depositEncrypted(address(l2ZoneToken), depositAmount, 0, payload, address(0)); vm.stopPrank(); // === STEP 3: Sequencer observes and relays with FAILED decryption === @@ -1119,15 +1127,17 @@ contract ZoneBridgeTest is BaseTest { // === STEP 2: Alice makes a regular deposit === vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), depositAmount * 2); - bytes32 h1 = - l1Portal.deposit(address(l2ZoneToken), alice, depositAmount, bytes32("regular")); + bytes32 h1 = l1Portal.deposit( + address(l2ZoneToken), alice, depositAmount, bytes32("regular"), address(0) + ); vm.stopPrank(); // === STEP 3: Bob makes an encrypted deposit === EncryptedDepositPayload memory payload = _makeEncryptedPayload(); vm.startPrank(bob); l2ZoneToken.approve(address(l1Portal), depositAmount); - bytes32 h2 = l1Portal.depositEncrypted(address(l2ZoneToken), depositAmount, 0, payload); + bytes32 h2 = + l1Portal.depositEncrypted(address(l2ZoneToken), depositAmount, 0, payload, address(0)); vm.stopPrank(); // === STEP 4: Carol makes another regular deposit === @@ -1137,7 +1147,9 @@ contract ZoneBridgeTest is BaseTest { l2ZoneToken.setMinter(address(this), false); vm.startPrank(carol); l2ZoneToken.approve(address(l1Portal), depositAmount); - bytes32 h3 = l1Portal.deposit(address(l2ZoneToken), carol, depositAmount, bytes32("carol")); + bytes32 h3 = l1Portal.deposit( + address(l2ZoneToken), carol, depositAmount, bytes32("carol"), address(0) + ); vm.stopPrank(); assertEq(l1Portal.currentDepositQueueHash(), h3, "L1 hash should be after 3rd deposit"); @@ -1151,7 +1163,8 @@ contract ZoneBridgeTest is BaseTest { sender: alice, to: alice, amount: depositAmount, - memo: bytes32("regular") + memo: bytes32("regular"), + bouncebackRecipient: address(0) }); bytes32 prevHash = l2Inbox.processedDepositQueueHash(); bytes32 hash1 = keccak256(abi.encode(DepositType.Regular, d1, prevHash)); @@ -1163,7 +1176,8 @@ contract ZoneBridgeTest is BaseTest { sender: bob, amount: netAmount, keyIndex: 0, - encrypted: payload + encrypted: payload, + bouncebackRecipient: address(0) }); bytes32 hash2 = keccak256(abi.encode(DepositType.Encrypted, ed, hash1)); assertEq(hash2, h2, "hash2 must match L1"); @@ -1174,7 +1188,8 @@ contract ZoneBridgeTest is BaseTest { sender: carol, to: carol, amount: depositAmount, - memo: bytes32("carol") + memo: bytes32("carol"), + bouncebackRecipient: address(0) }); bytes32 hash3 = keccak256(abi.encode(DepositType.Regular, d3, hash2)); assertEq(hash3, h3, "hash3 must match L1"); @@ -1251,7 +1266,8 @@ contract ZoneBridgeTest is BaseTest { vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), depositAmount); - bytes32 h1 = l1Portal.depositEncrypted(address(l2ZoneToken), depositAmount, 0, payload1); + bytes32 h1 = + l1Portal.depositEncrypted(address(l2ZoneToken), depositAmount, 0, payload1, address(0)); vm.stopPrank(); // === STEP 3: Sequencer rotates to second encryption key === @@ -1263,7 +1279,8 @@ contract ZoneBridgeTest is BaseTest { vm.startPrank(bob); l2ZoneToken.approve(address(l1Portal), depositAmount); - bytes32 h2 = l1Portal.depositEncrypted(address(l2ZoneToken), depositAmount, 1, payload2); + bytes32 h2 = + l1Portal.depositEncrypted(address(l2ZoneToken), depositAmount, 1, payload2, address(0)); vm.stopPrank(); assertEq(l1Portal.currentDepositQueueHash(), h2, "L1 hash after both deposits"); @@ -1275,7 +1292,8 @@ contract ZoneBridgeTest is BaseTest { sender: alice, amount: netAmount, keyIndex: 0, - encrypted: payload1 + encrypted: payload1, + bouncebackRecipient: address(0) }); bytes32 hash1 = keccak256(abi.encode(DepositType.Encrypted, ed1, prevHash)); assertEq(hash1, h1, "hash1 must match L1"); @@ -1285,7 +1303,8 @@ contract ZoneBridgeTest is BaseTest { sender: bob, amount: netAmount, keyIndex: 1, - encrypted: payload2 + encrypted: payload2, + bouncebackRecipient: address(0) }); bytes32 hash2 = keccak256(abi.encode(DepositType.Encrypted, ed2, hash1)); assertEq(hash2, h2, "hash2 must match L1"); diff --git a/docs/specs/test/zone/ZoneInbox.t.sol b/docs/specs/test/zone/ZoneInbox.t.sol index 91a7da53e..e2a7e0669 100644 --- a/docs/specs/test/zone/ZoneInbox.t.sol +++ b/docs/specs/test/zone/ZoneInbox.t.sol @@ -51,7 +51,7 @@ contract ZoneInboxTest is Test { tempoState.setMockStorageValue( mockPortal, bytes32(uint256(0)), bytes32(uint256(uint160(sequencer))) ); - inbox = new ZoneInbox(address(config), mockPortal, address(tempoState)); + inbox = new ZoneInbox(address(config), mockPortal, address(tempoState), address(0)); zoneToken.setMinter(address(inbox), true); } @@ -101,7 +101,8 @@ contract ZoneInboxTest is Test { sender: alice, to: bob, amount: 1000e6, - memo: bytes32("payment") + memo: bytes32("payment"), + bouncebackRecipient: address(0) }); // Calculate expected hash @@ -121,13 +122,28 @@ contract ZoneInboxTest is Test { function test_advanceTempo_multipleDeposits() public { Deposit[] memory deposits = new Deposit[](3); deposits[0] = Deposit({ - token: address(zoneToken), sender: alice, to: alice, amount: 100e6, memo: bytes32("d1") + token: address(zoneToken), + sender: alice, + to: alice, + amount: 100e6, + memo: bytes32("d1"), + bouncebackRecipient: address(0) }); deposits[1] = Deposit({ - token: address(zoneToken), sender: bob, to: bob, amount: 200e6, memo: bytes32("d2") + token: address(zoneToken), + sender: bob, + to: bob, + amount: 200e6, + memo: bytes32("d2"), + bouncebackRecipient: address(0) }); deposits[2] = Deposit({ - token: address(zoneToken), sender: alice, to: bob, amount: 300e6, memo: bytes32("d3") + token: address(zoneToken), + sender: alice, + to: bob, + amount: 300e6, + memo: bytes32("d3"), + bouncebackRecipient: address(0) }); // Calculate expected hash chain @@ -158,7 +174,8 @@ contract ZoneInboxTest is Test { sender: alice, to: bob, amount: 1000e6, - memo: bytes32("payment") + memo: bytes32("payment"), + bouncebackRecipient: address(0) }); // Set a different hash (simulating more deposits pending on Tempo) @@ -180,10 +197,20 @@ contract ZoneInboxTest is Test { // Partial processing is now allowed — the proof validates ancestor contiguity Deposit[] memory allDeposits = new Deposit[](2); allDeposits[0] = Deposit({ - token: address(zoneToken), sender: alice, to: alice, amount: 100e6, memo: bytes32("d1") + token: address(zoneToken), + sender: alice, + to: alice, + amount: 100e6, + memo: bytes32("d1"), + bouncebackRecipient: address(0) }); allDeposits[1] = Deposit({ - token: address(zoneToken), sender: bob, to: bob, amount: 200e6, memo: bytes32("d2") + token: address(zoneToken), + sender: bob, + to: bob, + amount: 200e6, + memo: bytes32("d2"), + bouncebackRecipient: address(0) }); // Set hash to be for both deposits @@ -244,10 +271,20 @@ contract ZoneInboxTest is Test { // First batch of deposits Deposit[] memory batch1 = new Deposit[](2); batch1[0] = Deposit({ - token: address(zoneToken), sender: alice, to: alice, amount: 100e6, memo: bytes32("d1") + token: address(zoneToken), + sender: alice, + to: alice, + amount: 100e6, + memo: bytes32("d1"), + bouncebackRecipient: address(0) }); batch1[1] = Deposit({ - token: address(zoneToken), sender: bob, to: bob, amount: 200e6, memo: bytes32("d2") + token: address(zoneToken), + sender: bob, + to: bob, + amount: 200e6, + memo: bytes32("d2"), + bouncebackRecipient: address(0) }); bytes32 h0 = bytes32(0); @@ -264,7 +301,12 @@ contract ZoneInboxTest is Test { // Second batch of deposits Deposit[] memory batch2 = new Deposit[](1); batch2[0] = Deposit({ - token: address(zoneToken), sender: alice, to: bob, amount: 500e6, memo: bytes32("d3") + token: address(zoneToken), + sender: alice, + to: bob, + amount: 500e6, + memo: bytes32("d3"), + bouncebackRecipient: address(0) }); bytes32 h3 = keccak256(abi.encode(DepositType.Regular, batch2[0], h2)); @@ -290,7 +332,8 @@ contract ZoneInboxTest is Test { sender: alice, to: bob, amount: 1000e6, - memo: bytes32("payment") + memo: bytes32("payment"), + bouncebackRecipient: address(0) }); bytes32 expectedHash = keccak256(abi.encode(DepositType.Regular, deposits[0], bytes32(0))); @@ -318,7 +361,8 @@ contract ZoneInboxTest is Test { sender: alice, to: bob, amount: 1000e6, - memo: bytes32("payment") + memo: bytes32("payment"), + bouncebackRecipient: address(0) }); bytes32 expectedHash = keccak256(abi.encode(DepositType.Regular, deposits[0], bytes32(0))); @@ -342,7 +386,12 @@ contract ZoneInboxTest is Test { function test_advanceTempo_zeroAmountDeposit() public { Deposit[] memory deposits = new Deposit[](1); deposits[0] = Deposit({ - token: address(zoneToken), sender: alice, to: bob, amount: 0, memo: bytes32("empty") + token: address(zoneToken), + sender: alice, + to: bob, + amount: 0, + memo: bytes32("empty"), + bouncebackRecipient: address(0) }); bytes32 expectedHash = keccak256(abi.encode(DepositType.Regular, deposits[0], bytes32(0))); @@ -383,7 +432,8 @@ contract ZoneInboxTest is Test { sender: alice, to: bob, amount: uint128(i + 1) * 1e6, - memo: bytes32(i) + memo: bytes32(i), + bouncebackRecipient: address(0) }); currentHash = keccak256(abi.encode(DepositType.Regular, deposits[i], currentHash)); } @@ -436,7 +486,8 @@ contract ZoneInboxTest is Test { ciphertext: new bytes(64), nonce: bytes12(0), tag: bytes16(0) - }) + }), + bouncebackRecipient: address(0) }); qd = QueuedDeposit({ depositType: DepositType.Encrypted, depositData: abi.encode(ed) }); } @@ -571,7 +622,12 @@ contract ZoneInboxTest is Test { // Build regular deposit Deposit memory d = Deposit({ - token: address(zoneToken), sender: alice, to: bob, amount: 100e6, memo: bytes32("d1") + token: address(zoneToken), + sender: alice, + to: bob, + amount: 100e6, + memo: bytes32("d1"), + bouncebackRecipient: address(0) }); QueuedDeposit memory qdRegular = QueuedDeposit({ depositType: DepositType.Regular, depositData: abi.encode(d) }); @@ -634,7 +690,12 @@ contract ZoneInboxTest is Test { function test_advanceTempo_extraDecryptionData() public { // Build a regular deposit only (no encrypted deposits) Deposit memory d = Deposit({ - token: address(zoneToken), sender: alice, to: bob, amount: 100e6, memo: bytes32("d1") + token: address(zoneToken), + sender: alice, + to: bob, + amount: 100e6, + memo: bytes32("d1"), + bouncebackRecipient: address(0) }); QueuedDeposit memory qd = QueuedDeposit({ depositType: DepositType.Regular, depositData: abi.encode(d) }); diff --git a/docs/specs/test/zone/ZoneIntegration.t.sol b/docs/specs/test/zone/ZoneIntegration.t.sol index 58ad468ca..7a2dc4c4c 100644 --- a/docs/specs/test/zone/ZoneIntegration.t.sol +++ b/docs/specs/test/zone/ZoneIntegration.t.sol @@ -113,8 +113,10 @@ contract ZoneIntegrationTest is BaseTest { l2TempoState.setMockStorageValue( address(l1Portal), bytes32(uint256(0)), bytes32(uint256(uint160(admin))) ); - l2Inbox = new ZoneInbox(address(l2Config), address(l1Portal), address(l2TempoState)); l2Outbox = new ZoneOutbox(address(l2Config)); + l2Inbox = new ZoneInbox( + address(l2Config), address(l1Portal), address(l2TempoState), address(l2Outbox) + ); l2ZoneToken.setMinter(address(l2Inbox), true); l2ZoneToken.setBurner(address(l2Outbox), true); @@ -200,18 +202,18 @@ contract ZoneIntegrationTest is BaseTest { // Alice, Bob, Charlie all deposit vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), 10_000e6); - l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32("alice1")); - l1Portal.deposit(address(l2ZoneToken), alice, 2000e6, bytes32("alice2")); + l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32("alice1"), address(0)); + l1Portal.deposit(address(l2ZoneToken), alice, 2000e6, bytes32("alice2"), address(0)); vm.stopPrank(); vm.startPrank(bob); l2ZoneToken.approve(address(l1Portal), 5000e6); - l1Portal.deposit(address(l2ZoneToken), bob, 3000e6, bytes32("bob1")); + l1Portal.deposit(address(l2ZoneToken), bob, 3000e6, bytes32("bob1"), address(0)); vm.stopPrank(); vm.startPrank(charlie); l2ZoneToken.approve(address(l1Portal), 2000e6); - l1Portal.deposit(address(l2ZoneToken), charlie, 500e6, bytes32("charlie1")); + l1Portal.deposit(address(l2ZoneToken), charlie, 500e6, bytes32("charlie1"), address(0)); vm.stopPrank(); // Build deposit array @@ -221,24 +223,32 @@ contract ZoneIntegrationTest is BaseTest { sender: alice, to: alice, amount: 1000e6, - memo: bytes32("alice1") + memo: bytes32("alice1"), + bouncebackRecipient: address(0) }); deposits[1] = Deposit({ token: address(l2ZoneToken), sender: alice, to: alice, amount: 2000e6, - memo: bytes32("alice2") + memo: bytes32("alice2"), + bouncebackRecipient: address(0) }); deposits[2] = Deposit({ - token: address(l2ZoneToken), sender: bob, to: bob, amount: 3000e6, memo: bytes32("bob1") + token: address(l2ZoneToken), + sender: bob, + to: bob, + amount: 3000e6, + memo: bytes32("bob1"), + bouncebackRecipient: address(0) }); deposits[3] = Deposit({ token: address(l2ZoneToken), sender: charlie, to: charlie, amount: 500e6, - memo: bytes32("charlie1") + memo: bytes32("charlie1"), + bouncebackRecipient: address(0) }); // Set up L2 mock — hash chain uses l2ZoneToken consistently @@ -276,8 +286,10 @@ contract ZoneIntegrationTest is BaseTest { // Batch 1: Two deposits vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), 10_000e6); - bytes32 d1 = l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32("d1")); - bytes32 d2 = l1Portal.deposit(address(l2ZoneToken), alice, 2000e6, bytes32("d2")); + bytes32 d1 = + l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32("d1"), address(0)); + bytes32 d2 = + l1Portal.deposit(address(l2ZoneToken), alice, 2000e6, bytes32("d2"), address(0)); vm.stopPrank(); // Process only first deposit @@ -287,7 +299,8 @@ contract ZoneIntegrationTest is BaseTest { sender: alice, to: alice, amount: 1000e6, - memo: bytes32("d1") + memo: bytes32("d1"), + bouncebackRecipient: address(0) }); // Deposit hash uses l2ZoneToken consistently @@ -321,7 +334,7 @@ contract ZoneIntegrationTest is BaseTest { // More deposits arrive vm.prank(alice); - l1Portal.deposit(address(l2ZoneToken), alice, 3000e6, bytes32("d3")); + l1Portal.deposit(address(l2ZoneToken), alice, 3000e6, bytes32("d3"), address(0)); // Process remaining deposits Deposit[] memory batch2 = new Deposit[](2); @@ -330,14 +343,16 @@ contract ZoneIntegrationTest is BaseTest { sender: alice, to: alice, amount: 2000e6, - memo: bytes32("d2") + memo: bytes32("d2"), + bouncebackRecipient: address(0) }); batch2[1] = Deposit({ token: address(l2ZoneToken), sender: alice, to: alice, amount: 3000e6, - memo: bytes32("d3") + memo: bytes32("d3"), + bouncebackRecipient: address(0) }); // Compute L2 hash chain continuing from l2Hash1 @@ -362,7 +377,7 @@ contract ZoneIntegrationTest is BaseTest { vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), 10_000e6); bytes32 depositHash = - l1Portal.deposit(address(l2ZoneToken), alice, 5000e6, bytes32("deposit")); + l1Portal.deposit(address(l2ZoneToken), alice, 5000e6, bytes32("deposit"), address(0)); vm.stopPrank(); // Process deposit on L2 @@ -372,7 +387,8 @@ contract ZoneIntegrationTest is BaseTest { sender: alice, to: alice, amount: 5000e6, - memo: bytes32("deposit") + memo: bytes32("deposit"), + bouncebackRecipient: address(0) }); l2TempoState.setMockStorageValue( address(l1Portal), PORTAL_CURRENT_DEPOSIT_QUEUE_HASH_SLOT, depositHash @@ -433,8 +449,9 @@ contract ZoneIntegrationTest is BaseTest { // Initial deposit vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), 100_000e6); - bytes32 depositHash = - l1Portal.deposit(address(l2ZoneToken), alice, 50_000e6, bytes32("big deposit")); + bytes32 depositHash = l1Portal.deposit( + address(l2ZoneToken), alice, 50_000e6, bytes32("big deposit"), address(0) + ); vm.stopPrank(); // Process on L2 @@ -444,7 +461,8 @@ contract ZoneIntegrationTest is BaseTest { sender: alice, to: alice, amount: 50_000e6, - memo: bytes32("big deposit") + memo: bytes32("big deposit"), + bouncebackRecipient: address(0) }); l2TempoState.setMockStorageValue( address(l1Portal), PORTAL_CURRENT_DEPOSIT_QUEUE_HASH_SLOT, depositHash @@ -565,12 +583,12 @@ contract ZoneIntegrationTest is BaseTest { // Phase 1: Initial deposits vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), 100_000e6); - l1Portal.deposit(address(l2ZoneToken), alice, 10_000e6, bytes32("d1")); + l1Portal.deposit(address(l2ZoneToken), alice, 10_000e6, bytes32("d1"), address(0)); vm.stopPrank(); vm.startPrank(bob); l2ZoneToken.approve(address(l1Portal), 100_000e6); - bytes32 d2 = l1Portal.deposit(address(l2ZoneToken), bob, 5000e6, bytes32("d2")); + bytes32 d2 = l1Portal.deposit(address(l2ZoneToken), bob, 5000e6, bytes32("d2"), address(0)); vm.stopPrank(); // Process both deposits @@ -580,10 +598,16 @@ contract ZoneIntegrationTest is BaseTest { sender: alice, to: alice, amount: 10_000e6, - memo: bytes32("d1") + memo: bytes32("d1"), + bouncebackRecipient: address(0) }); deposits1[1] = Deposit({ - token: address(l2ZoneToken), sender: bob, to: bob, amount: 5000e6, memo: bytes32("d2") + token: address(l2ZoneToken), + sender: bob, + to: bob, + amount: 5000e6, + memo: bytes32("d2"), + bouncebackRecipient: address(0) }); l2TempoState.setMockStorageValue( @@ -608,7 +632,8 @@ contract ZoneIntegrationTest is BaseTest { // Phase 3: More deposits arrive while withdrawals are pending vm.startPrank(charlie); l2ZoneToken.approve(address(l1Portal), 20_000e6); - bytes32 d3 = l1Portal.deposit(address(l2ZoneToken), charlie, 7500e6, bytes32("d3")); + bytes32 d3 = + l1Portal.deposit(address(l2ZoneToken), charlie, 7500e6, bytes32("d3"), address(0)); vm.stopPrank(); // Submit batch with withdrawals @@ -632,7 +657,8 @@ contract ZoneIntegrationTest is BaseTest { sender: charlie, to: charlie, amount: 7500e6, - memo: bytes32("d3") + memo: bytes32("d3"), + bouncebackRecipient: address(0) }); l2TempoState.setMockStorageValue( @@ -672,7 +698,8 @@ contract ZoneIntegrationTest is BaseTest { // Deposit 10000 vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), 10_000e6); - bytes32 d1 = l1Portal.deposit(address(l2ZoneToken), alice, 10_000e6, bytes32("d1")); + bytes32 d1 = + l1Portal.deposit(address(l2ZoneToken), alice, 10_000e6, bytes32("d1"), address(0)); vm.stopPrank(); Deposit[] memory deposits = new Deposit[](1); @@ -681,7 +708,8 @@ contract ZoneIntegrationTest is BaseTest { sender: alice, to: alice, amount: 10_000e6, - memo: bytes32("d1") + memo: bytes32("d1"), + bouncebackRecipient: address(0) }); l2TempoState.setMockStorageValue( address(l1Portal), PORTAL_CURRENT_DEPOSIT_QUEUE_HASH_SLOT, d1 @@ -716,7 +744,7 @@ contract ZoneIntegrationTest is BaseTest { // Make a deposit to get a non-zero currentDepositQueueHash vm.startPrank(alice); l2ZoneToken.approve(address(l1Portal), 1000e6); - l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32("layout-test")); + l1Portal.deposit(address(l2ZoneToken), alice, 1000e6, bytes32("layout-test"), address(0)); vm.stopPrank(); // Read via vm.load using our constant diff --git a/docs/specs/test/zone/ZoneOutbox.t.sol b/docs/specs/test/zone/ZoneOutbox.t.sol index 7428bec7e..9142aa17d 100644 --- a/docs/specs/test/zone/ZoneOutbox.t.sol +++ b/docs/specs/test/zone/ZoneOutbox.t.sol @@ -42,8 +42,8 @@ contract ZoneOutboxTest is Test { tempoState.setMockStorageValue( mockPortal, bytes32(uint256(0)), bytes32(uint256(uint160(sequencer))) ); - inbox = new ZoneInbox(address(config), mockPortal, address(tempoState)); outbox = new ZoneOutbox(address(config)); + inbox = new ZoneInbox(address(config), mockPortal, address(tempoState), address(outbox)); // Grant minter role to inbox and burner role to outbox zoneToken.setMinter(address(inbox), true); diff --git a/docs/specs/test/zone/ZonePortal.t.sol b/docs/specs/test/zone/ZonePortal.t.sol index 2101ae8ab..3c60a71ac 100644 --- a/docs/specs/test/zone/ZonePortal.t.sol +++ b/docs/specs/test/zone/ZonePortal.t.sol @@ -251,7 +251,8 @@ contract ZonePortalTest is BaseTest { // Approve and deposit vm.startPrank(alice); pathUSD.approve(address(portal), depositAmount); - bytes32 hash1 = portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo1")); + bytes32 hash1 = + portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo1"), address(0)); vm.stopPrank(); // Verify hash chain updated @@ -269,13 +270,14 @@ contract ZonePortalTest is BaseTest { // First deposit from alice vm.startPrank(alice); pathUSD.approve(address(portal), amount1); - bytes32 hash1 = portal.deposit(address(pathUSD), alice, amount1, bytes32("memo1")); + bytes32 hash1 = + portal.deposit(address(pathUSD), alice, amount1, bytes32("memo1"), address(0)); vm.stopPrank(); // Second deposit from bob vm.startPrank(bob); pathUSD.approve(address(portal), amount2); - bytes32 hash2 = portal.deposit(address(pathUSD), bob, amount2, bytes32("memo2")); + bytes32 hash2 = portal.deposit(address(pathUSD), bob, amount2, bytes32("memo2"), address(0)); vm.stopPrank(); // Hash chain should have updated @@ -298,15 +300,15 @@ contract ZonePortalTest is BaseTest { assertEq(initialHash, bytes32(0)); // After deposit 1 - portal.deposit(address(pathUSD), alice, amount, bytes32("d1")); + portal.deposit(address(pathUSD), alice, amount, bytes32("d1"), address(0)); bytes32 hash1 = portal.currentDepositQueueHash(); // After deposit 2: hash2 = keccak256(abi.encode(message2, hash1)) - portal.deposit(address(pathUSD), alice, amount, bytes32("d2")); + portal.deposit(address(pathUSD), alice, amount, bytes32("d2"), address(0)); bytes32 hash2 = portal.currentDepositQueueHash(); // After deposit 3: hash3 = keccak256(abi.encode(message3, hash2)) - portal.deposit(address(pathUSD), alice, amount, bytes32("d3")); + portal.deposit(address(pathUSD), alice, amount, bytes32("d3"), address(0)); bytes32 hash3 = portal.currentDepositQueueHash(); vm.stopPrank(); @@ -349,7 +351,7 @@ contract ZonePortalTest is BaseTest { vm.startPrank(alice); pathUSD.approve(address(portal), depositAmount); vm.expectRevert(IZonePortal.DepositPolicyForbids.selector); - portal.deposit(address(pathUSD), bob, depositAmount, bytes32("memo")); + portal.deposit(address(pathUSD), bob, depositAmount, bytes32("memo"), address(0)); vm.stopPrank(); } @@ -384,7 +386,8 @@ contract ZonePortalTest is BaseTest { vm.startPrank(alice); pathUSD.approve(address(portal), depositAmount); - bytes32 depositHash = portal.deposit(address(pathUSD), bob, depositAmount, bytes32("memo")); + bytes32 depositHash = + portal.deposit(address(pathUSD), bob, depositAmount, bytes32("memo"), address(0)); vm.stopPrank(); assertEq(portal.currentDepositQueueHash(), depositHash); @@ -401,7 +404,7 @@ contract ZonePortalTest is BaseTest { vm.startPrank(alice); pathUSD.approve(address(portal), depositAmount); bytes32 depositHash = - portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo")); + portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo"), address(0)); vm.stopPrank(); // Submit a batch (as sequencer) @@ -504,7 +507,7 @@ contract ZonePortalTest is BaseTest { uint128 depositAmount = 1000e6; vm.startPrank(alice); pathUSD.approve(address(portal), depositAmount); - portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo")); + portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo"), address(0)); vm.stopPrank(); // Create a withdrawal and add to queue via batch @@ -553,7 +556,7 @@ contract ZonePortalTest is BaseTest { uint128 depositAmount = 2000e6; vm.startPrank(alice); pathUSD.approve(address(portal), depositAmount); - portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo")); + portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo"), address(0)); vm.stopPrank(); // Create two withdrawals in the same batch @@ -611,7 +614,7 @@ contract ZonePortalTest is BaseTest { uint128 depositAmount = 3000e6; vm.startPrank(alice); pathUSD.approve(address(portal), depositAmount); - portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo")); + portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo"), address(0)); vm.stopPrank(); // Batch 1: withdrawal to bob @@ -676,7 +679,7 @@ contract ZonePortalTest is BaseTest { uint128 depositAmount = 1000e6; vm.startPrank(alice); pathUSD.approve(address(portal), depositAmount); - portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo")); + portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo"), address(0)); vm.stopPrank(); uint256 tailBefore = portal.withdrawalQueueTail(); @@ -710,7 +713,7 @@ contract ZonePortalTest is BaseTest { uint128 depositAmount = 1000e6; vm.startPrank(alice); pathUSD.approve(address(portal), depositAmount); - portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo")); + portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo"), address(0)); vm.stopPrank(); // Create withdrawal with callback @@ -760,7 +763,7 @@ contract ZonePortalTest is BaseTest { uint128 depositAmount = 1000e6; vm.startPrank(alice); pathUSD.approve(address(portal), depositAmount); - portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo")); + portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo"), address(0)); vm.stopPrank(); bytes32 depositHashBefore = portal.currentDepositQueueHash(); @@ -814,7 +817,7 @@ contract ZonePortalTest is BaseTest { uint128 depositAmount = 1000e6; vm.startPrank(alice); pathUSD.approve(address(portal), depositAmount); - portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo")); + portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo"), address(0)); vm.stopPrank(); bytes32 depositHashBefore = portal.currentDepositQueueHash(); @@ -864,7 +867,7 @@ contract ZonePortalTest is BaseTest { uint128 depositAmount = 1000e6; vm.startPrank(alice); pathUSD.approve(address(portal), depositAmount); - portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo")); + portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo"), address(0)); vm.stopPrank(); bytes32 depositHashBefore = portal.currentDepositQueueHash(); @@ -924,7 +927,7 @@ contract ZonePortalTest is BaseTest { uint128 depositAmount = 1000e6; vm.startPrank(alice); pathUSD.approve(address(portal), depositAmount); - portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo")); + portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo"), address(0)); vm.stopPrank(); Withdrawal memory w = @@ -961,7 +964,7 @@ contract ZonePortalTest is BaseTest { uint128 depositAmount = 1000e6; vm.startPrank(alice); pathUSD.approve(address(portal), depositAmount); - portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo")); + portal.deposit(address(pathUSD), alice, depositAmount, bytes32("memo"), address(0)); vm.stopPrank(); Withdrawal memory w = @@ -1007,8 +1010,8 @@ contract ZonePortalTest is BaseTest { // Make deposits vm.startPrank(alice); pathUSD.approve(address(portal), 3000e6); - bytes32 h1 = portal.deposit(address(pathUSD), alice, 1000e6, bytes32("d1")); - bytes32 h2 = portal.deposit(address(pathUSD), alice, 1000e6, bytes32("d2")); + bytes32 h1 = portal.deposit(address(pathUSD), alice, 1000e6, bytes32("d1"), address(0)); + bytes32 h2 = portal.deposit(address(pathUSD), alice, 1000e6, bytes32("d2"), address(0)); vm.stopPrank(); // currentDepositQueueHash should be h2 (latest) @@ -1036,7 +1039,7 @@ contract ZonePortalTest is BaseTest { // New deposit arrives vm.startPrank(alice); - bytes32 h3 = portal.deposit(address(pathUSD), alice, 1000e6, bytes32("d3")); + bytes32 h3 = portal.deposit(address(pathUSD), alice, 1000e6, bytes32("d3"), address(0)); vm.stopPrank(); // currentDepositQueueHash updated @@ -1198,7 +1201,7 @@ contract ZonePortalTest is BaseTest { // Make a deposit first vm.startPrank(alice); pathUSD.approve(address(portal), 1000e6); - portal.deposit(address(pathUSD), alice, 1000e6, bytes32("memo")); + portal.deposit(address(pathUSD), alice, 1000e6, bytes32("memo"), address(0)); vm.stopPrank(); bytes32 depositHash = portal.currentDepositQueueHash(); @@ -1231,8 +1234,8 @@ contract ZonePortalTest is BaseTest { // Make deposits vm.startPrank(alice); pathUSD.approve(address(portal), 3000e6); - bytes32 h1 = portal.deposit(address(pathUSD), alice, 1000e6, bytes32("d1")); - bytes32 h2 = portal.deposit(address(pathUSD), alice, 1000e6, bytes32("d2")); + bytes32 h1 = portal.deposit(address(pathUSD), alice, 1000e6, bytes32("d1"), address(0)); + bytes32 h2 = portal.deposit(address(pathUSD), alice, 1000e6, bytes32("d2"), address(0)); vm.stopPrank(); vm.roll(block.number + 1); @@ -1277,7 +1280,7 @@ contract ZonePortalTest is BaseTest { function test_withdrawalQueue_emptyBatchDoesNotIncreaseTail() public { vm.startPrank(alice); pathUSD.approve(address(portal), 1000e6); - portal.deposit(address(pathUSD), alice, 1000e6, bytes32("")); + portal.deposit(address(pathUSD), alice, 1000e6, bytes32(""), address(0)); vm.stopPrank(); bytes32 depositHash = portal.currentDepositQueueHash(); @@ -1308,7 +1311,7 @@ contract ZonePortalTest is BaseTest { // Fund portal vm.startPrank(alice); pathUSD.approve(address(portal), 10_000e6); - portal.deposit(address(pathUSD), alice, 10_000e6, bytes32("")); + portal.deposit(address(pathUSD), alice, 10_000e6, bytes32(""), address(0)); vm.stopPrank(); bytes32 depositHash = portal.currentDepositQueueHash(); @@ -1367,7 +1370,7 @@ contract ZonePortalTest is BaseTest { // Fund portal vm.startPrank(alice); pathUSD.approve(address(portal), 1000e6); - portal.deposit(address(pathUSD), alice, 1000e6, bytes32("")); + portal.deposit(address(pathUSD), alice, 1000e6, bytes32(""), address(0)); vm.stopPrank(); bytes32 depositHashBefore = portal.currentDepositQueueHash(); @@ -1412,7 +1415,7 @@ contract ZonePortalTest is BaseTest { // Fund portal vm.startPrank(alice); pathUSD.approve(address(portal), 1000e6); - portal.deposit(address(pathUSD), alice, 1000e6, bytes32("")); + portal.deposit(address(pathUSD), alice, 1000e6, bytes32(""), address(0)); vm.stopPrank(); bytes32 depositHash = portal.currentDepositQueueHash(); @@ -1451,7 +1454,7 @@ contract ZonePortalTest is BaseTest { // Fund portal vm.startPrank(alice); pathUSD.approve(address(portal), 1000e6); - portal.deposit(address(pathUSD), alice, 1000e6, bytes32("")); + portal.deposit(address(pathUSD), alice, 1000e6, bytes32(""), address(0)); vm.stopPrank(); bytes32 depositHash = portal.currentDepositQueueHash(); @@ -1497,7 +1500,7 @@ contract ZonePortalTest is BaseTest { // Fund portal vm.startPrank(alice); pathUSD.approve(address(portal), 1000e6); - portal.deposit(address(pathUSD), alice, 1000e6, bytes32("")); + portal.deposit(address(pathUSD), alice, 1000e6, bytes32(""), address(0)); vm.stopPrank(); bytes32 depositHashBefore = portal.currentDepositQueueHash(); @@ -1541,7 +1544,8 @@ contract ZonePortalTest is BaseTest { sender: address(portal), to: bob, amount: 500e6, - memo: bytes32(0) + memo: bytes32(0), + bouncebackRecipient: address(0) }); bytes32 expectedHash = keccak256(abi.encode(DepositType.Regular, expectedBounceBack, depositHashBefore)); @@ -1555,7 +1559,7 @@ contract ZonePortalTest is BaseTest { function test_withdrawalBatchIndex_incrementsOnEachBatch() public { vm.startPrank(alice); pathUSD.approve(address(portal), 3000e6); - portal.deposit(address(pathUSD), alice, 1000e6, bytes32("")); + portal.deposit(address(pathUSD), alice, 1000e6, bytes32(""), address(0)); vm.stopPrank(); bytes32 depositHash = portal.currentDepositQueueHash(); @@ -1624,16 +1628,17 @@ contract ZonePortalTest is BaseTest { sender: alice, to: bob, amount: netAmount, - memo: bytes32("test") + memo: bytes32("test"), + bouncebackRecipient: address(0) }), bytes32(0) ) ); emit IZonePortal.DepositMade( - expectedHash, alice, address(pathUSD), bob, netAmount, fee, bytes32("test") + expectedHash, alice, address(pathUSD), bob, netAmount, fee, bytes32("test"), address(0) ); - portal.deposit(address(pathUSD), bob, 500e6, bytes32("test")); + portal.deposit(address(pathUSD), bob, 500e6, bytes32("test"), address(0)); vm.stopPrank(); } @@ -1641,7 +1646,7 @@ contract ZonePortalTest is BaseTest { // Setup withdrawal vm.startPrank(alice); pathUSD.approve(address(portal), 1000e6); - portal.deposit(address(pathUSD), alice, 1000e6, bytes32("")); + portal.deposit(address(pathUSD), alice, 1000e6, bytes32(""), address(0)); vm.stopPrank(); Withdrawal memory w = @@ -1671,7 +1676,7 @@ contract ZonePortalTest is BaseTest { // Setup withdrawal with failing callback vm.startPrank(alice); pathUSD.approve(address(portal), 1000e6); - portal.deposit(address(pathUSD), alice, 1000e6, bytes32("")); + portal.deposit(address(pathUSD), alice, 1000e6, bytes32(""), address(0)); vm.stopPrank(); Withdrawal memory w = _withdrawal( @@ -1945,8 +1950,9 @@ contract ZonePortalTest is BaseTest { uint128 depositAmount = 1000e6; vm.startPrank(alice); pathUSD.approve(address(portal), depositAmount); - bytes32 hash = - portal.depositEncrypted(address(pathUSD), depositAmount, 0, _makeEncryptedPayload()); + bytes32 hash = portal.depositEncrypted( + address(pathUSD), depositAmount, 0, _makeEncryptedPayload(), address(0) + ); vm.stopPrank(); assertEq(portal.currentDepositQueueHash(), hash); @@ -1964,7 +1970,8 @@ contract ZonePortalTest is BaseTest { vm.startPrank(alice); pathUSD.approve(address(portal), depositAmount); - bytes32 hash = portal.depositEncrypted(address(pathUSD), depositAmount, 0, encrypted); + bytes32 hash = + portal.depositEncrypted(address(pathUSD), depositAmount, 0, encrypted, address(0)); vm.stopPrank(); // Reconstruct expected hash using the same encoding as DepositQueueLib @@ -1973,7 +1980,8 @@ contract ZonePortalTest is BaseTest { sender: alice, amount: netAmount, keyIndex: 0, - encrypted: encrypted + encrypted: encrypted, + bouncebackRecipient: address(0) }); bytes32 expectedHash = keccak256(abi.encode(DepositType.Encrypted, ed, bytes32(0))); assertEq(hash, expectedHash); @@ -1987,10 +1995,12 @@ contract ZonePortalTest is BaseTest { // Regular deposit from alice vm.startPrank(alice); pathUSD.approve(address(portal), amount * 3); - bytes32 h1 = portal.deposit(address(pathUSD), alice, amount, bytes32("memo")); + bytes32 h1 = portal.deposit(address(pathUSD), alice, amount, bytes32("memo"), address(0)); // Encrypted deposit from alice - bytes32 h2 = portal.depositEncrypted(address(pathUSD), amount, 0, _makeEncryptedPayload()); + bytes32 h2 = portal.depositEncrypted( + address(pathUSD), amount, 0, _makeEncryptedPayload(), address(0) + ); vm.stopPrank(); // Both should update the same queue @@ -2011,7 +2021,9 @@ contract ZonePortalTest is BaseTest { vm.startPrank(alice); pathUSD.approve(address(portal), depositAmount); - portal.depositEncrypted(address(pathUSD), depositAmount, 0, _makeEncryptedPayload()); + portal.depositEncrypted( + address(pathUSD), depositAmount, 0, _makeEncryptedPayload(), address(0) + ); vm.stopPrank(); assertEq(pathUSD.balanceOf(alice), aliceBefore - depositAmount); @@ -2037,7 +2049,8 @@ contract ZonePortalTest is BaseTest { sender: alice, amount: netAmount, keyIndex: 0, - encrypted: encrypted + encrypted: encrypted, + bouncebackRecipient: address(0) }); bytes32 expectedHash = keccak256(abi.encode(DepositType.Encrypted, ed, bytes32(0))); @@ -2055,7 +2068,7 @@ contract ZonePortalTest is BaseTest { encrypted.nonce, encrypted.tag ); - portal.depositEncrypted(address(pathUSD), depositAmount, 0, encrypted); + portal.depositEncrypted(address(pathUSD), depositAmount, 0, encrypted, address(0)); vm.stopPrank(); } @@ -2076,7 +2089,9 @@ contract ZonePortalTest is BaseTest { // Should revert with EncryptionKeyExpired for key index 0 vm.expectRevert(); - portal.depositEncrypted(address(pathUSD), depositAmount, 0, _makeEncryptedPayload()); + portal.depositEncrypted( + address(pathUSD), depositAmount, 0, _makeEncryptedPayload(), address(0) + ); vm.stopPrank(); } @@ -2087,7 +2102,9 @@ contract ZonePortalTest is BaseTest { // No keys set, index 0 is invalid vm.expectRevert(abi.encodeWithSelector(IZonePortal.InvalidEncryptionKeyIndex.selector, 0)); - portal.depositEncrypted(address(pathUSD), depositAmount, 0, _makeEncryptedPayload()); + portal.depositEncrypted( + address(pathUSD), depositAmount, 0, _makeEncryptedPayload(), address(0) + ); vm.stopPrank(); } @@ -2107,7 +2124,7 @@ contract ZonePortalTest is BaseTest { }); vm.expectRevert(IZonePortal.InvalidEphemeralPubkey.selector); - portal.depositEncrypted(address(pathUSD), depositAmount, 0, encrypted); + portal.depositEncrypted(address(pathUSD), depositAmount, 0, encrypted, address(0)); vm.stopPrank(); } @@ -2127,7 +2144,7 @@ contract ZonePortalTest is BaseTest { }); vm.expectRevert(IZonePortal.InvalidEphemeralPubkey.selector); - portal.depositEncrypted(address(pathUSD), depositAmount, 0, encrypted); + portal.depositEncrypted(address(pathUSD), depositAmount, 0, encrypted, address(0)); vm.stopPrank(); } @@ -2139,7 +2156,7 @@ contract ZonePortalTest is BaseTest { pathUSD.approve(address(portal), 100_000); vm.expectRevert(IZonePortal.DepositTooSmall.selector); - portal.depositEncrypted(address(pathUSD), 100_000, 0, _makeEncryptedPayload()); // amount == fee + portal.depositEncrypted(address(pathUSD), 100_000, 0, _makeEncryptedPayload(), address(0)); // amount == fee vm.stopPrank(); } @@ -2155,7 +2172,7 @@ contract ZonePortalTest is BaseTest { vm.expectRevert( abi.encodeWithSelector(IZonePortal.InvalidCiphertextLength.selector, 63, 64) ); - portal.depositEncrypted(address(pathUSD), 1000e6, 0, payload); + portal.depositEncrypted(address(pathUSD), 1000e6, 0, payload, address(0)); vm.stopPrank(); } @@ -2171,7 +2188,7 @@ contract ZonePortalTest is BaseTest { vm.expectRevert( abi.encodeWithSelector(IZonePortal.InvalidCiphertextLength.selector, 65, 64) ); - portal.depositEncrypted(address(pathUSD), 1000e6, 0, payload); + portal.depositEncrypted(address(pathUSD), 1000e6, 0, payload, address(0)); vm.stopPrank(); } @@ -2185,7 +2202,7 @@ contract ZonePortalTest is BaseTest { pathUSD.approve(address(portal), 1000e6); vm.expectRevert(abi.encodeWithSelector(IZonePortal.InvalidCiphertextLength.selector, 0, 64)); - portal.depositEncrypted(address(pathUSD), 1000e6, 0, payload); + portal.depositEncrypted(address(pathUSD), 1000e6, 0, payload, address(0)); vm.stopPrank(); } @@ -2201,7 +2218,7 @@ contract ZonePortalTest is BaseTest { vm.expectRevert( abi.encodeWithSelector(IZonePortal.InvalidCiphertextLength.selector, 1024, 64) ); - portal.depositEncrypted(address(pathUSD), 1000e6, 0, payload); + portal.depositEncrypted(address(pathUSD), 1000e6, 0, payload, address(0)); vm.stopPrank(); } diff --git a/tempo.nu b/tempo.nu new file mode 100755 index 000000000..c55b4c23b --- /dev/null +++ b/tempo.nu @@ -0,0 +1,629 @@ +#!/usr/bin/env nu + +# Tempo local utilities + +const BENCH_DIR = "contrib/bench" +const LOCALNET_DIR = "localnet" +const LOGS_DIR = "contrib/bench/logs" +const RUSTFLAGS = "-C target-cpu=native" +const DEFAULT_PROFILE = "profiling" +const DEFAULT_FEATURES = "jemalloc,asm-keccak" + +# Preset weight configurations: [tip20, erc20, swap, order] +const PRESETS = { + tip20: [1.0, 0.0, 0.0, 0.0], + erc20: [0.0, 1.0, 0.0, 0.0], + swap: [0.0, 0.0, 1.0, 0.0], + order: [0.0, 0.0, 0.0, 1.0], + "tempo-mix": [0.8, 0, 0.19, 0.01] +} + +# ============================================================================ +# Helper functions +# ============================================================================ + +# Convert consensus port to node index (e.g., 8000 -> 0, 8100 -> 1) +def port-to-node-index [port: int] { + ($port - 8000) / 100 | into int +} + +# Build log filter args based on --loud flag +def log-filter-args [loud: bool] { + if $loud { [] } else { ["--log.stdout.filter" "warn"] } +} + +# Wrap command with samply if enabled +def wrap-samply [cmd: list, samply: bool, samply_args: list] { + if $samply { + ["samply" "record" ...$samply_args "--" ...$cmd] + } else { + $cmd + } +} + +# Validate mode is either "dev" or "consensus" +def validate-mode [mode: string] { + if $mode != "dev" and $mode != "consensus" { + print $"Unknown mode: ($mode). Use 'dev' or 'consensus'." + exit 1 + } +} + +# Build tempo binary with cargo +def build-tempo [bins: list, profile: string, features: string] { + let bin_args = ($bins | each { |bin| ["--bin" $bin] } | flatten) + let build_cmd = ["cargo" "build" "--profile" $profile "--features" $features] | append $bin_args + print $"Building ($bins | str join ', '): `($build_cmd | str join ' ')`..." + with-env { RUSTFLAGS: $RUSTFLAGS } { + run-external ($build_cmd | first) ...($build_cmd | skip 1) + } +} + +# Find tempo process PIDs (excluding tempo-bench) +def find-tempo-pids [] { + ps | where name =~ "tempo" | where name !~ "tempo-bench" | get pid +} + +# ============================================================================ +# Infra commands +# ============================================================================ + +# Start the observability stack (Grafana + Prometheus) +def "main infra up" [] { + print "Starting observability stack..." + docker compose -f $"($BENCH_DIR)/docker-compose.yml" up -d + print "Grafana available at http://localhost:3000 (admin/admin)" + print "Prometheus available at http://localhost:9090" +} + +# Stop the observability stack +def "main infra down" [] { + print "Stopping observability stack..." + docker compose -f $"($BENCH_DIR)/docker-compose.yml" down +} + +# ============================================================================ +# Kill command +# ============================================================================ + +# Kill any running tempo processes and cleanup +def "main kill" [ + --prompt # Prompt before killing (for interactive use) +] { + let pids = (find-tempo-pids) + let has_stale_ipc = ("/tmp/reth.ipc" | path exists) + + if ($pids | length) == 0 and not $has_stale_ipc { + print "No tempo processes or stale IPC socket found." + return + } + + if ($pids | length) > 0 { + print $"Found ($pids | length) running tempo process\(es\)." + } + if $has_stale_ipc { + print "Found stale /tmp/reth.ipc socket." + } + + let should_kill = if $prompt { + let answer = (input "Clean up? [Y/n] " | str trim | str downcase) + $answer == "" or $answer == "y" or $answer == "yes" + } else { + true + } + + if not $should_kill { + print "Aborting." + exit 1 + } + + if ($pids | length) > 0 { + print $"Sending SIGINT to ($pids | length) tempo processes..." + for pid in $pids { + kill -s 2 $pid + } + } + + # Remove stale IPC socket + if $has_stale_ipc { + rm /tmp/reth.ipc + print "Removed /tmp/reth.ipc" + } + print "Done." +} + +# ============================================================================ +# Localnet command +# ============================================================================ + +# Run Tempo localnet +def "main localnet" [ + --mode: string = "dev" # Mode: "dev" or "consensus" + --nodes: int = 3 # Number of validators (consensus mode) + --accounts: int = 1000 # Number of genesis accounts + --genesis: string = "" # Custom genesis file path (skips generation) + --samply # Enable samply profiling (foreground node only) + --samply-args: string = "" # Additional samply arguments (space-separated) + --reset # Wipe and regenerate localnet data + --profile: string = $DEFAULT_PROFILE # Cargo build profile + --features: string = $DEFAULT_FEATURES # Cargo features + --loud # Show all node logs (WARN/ERROR shown by default) + --node-args: string = "" # Additional node arguments (space-separated) + --skip-build # Skip building (assumes binary is already built) + --force # Kill dangling processes without prompting +] { + validate-mode $mode + + # Check for dangling processes or stale IPC socket + let pids = (find-tempo-pids) + let has_stale_ipc = ("/tmp/reth.ipc" | path exists) + if ($pids | length) > 0 or $has_stale_ipc { + main kill --prompt=($force | not $in) + } + + # Parse custom args + let extra_args = if $node_args == "" { [] } else { $node_args | split row " " } + let samply_args_list = if $samply_args == "" { [] } else { $samply_args | split row " " } + + # Build first (unless skipped) + if not $skip_build { + build-tempo ["tempo"] $profile $features + } + + if $mode == "dev" { + if $nodes != 3 { + print "Error: --nodes is only valid with --mode consensus" + exit 1 + } + run-dev-node $accounts $genesis $samply $samply_args_list $reset $profile $loud $extra_args + } else { + run-consensus-nodes $nodes $accounts $genesis $samply $samply_args_list $reset $profile $loud $extra_args + } +} + +# ============================================================================ +# Dev mode +# ============================================================================ + +def run-dev-node [accounts: int, genesis: string, samply: bool, samply_args: list, reset: bool, profile: string, loud: bool, extra_args: list] { + let genesis_path = if $genesis != "" { + $genesis + } else { + let default_genesis = $"($LOCALNET_DIR)/genesis.json" + let needs_generation = $reset or (not ($default_genesis | path exists)) + + if $needs_generation { + if $reset { + print "Resetting localnet data..." + } else { + print "Genesis not found, generating..." + } + rm -rf $LOCALNET_DIR + mkdir $LOCALNET_DIR + print $"Generating genesis with ($accounts) accounts..." + cargo run -p tempo-xtask --profile $profile -- generate-genesis --output $LOCALNET_DIR -a $accounts --no-dkg-in-genesis + } + $default_genesis + } + + let tempo_bin = if $profile == "dev" { + "./target/debug/tempo" + } else { + $"./target/($profile)/tempo" + } + let datadir = $"($LOCALNET_DIR)/reth" + let log_dir = $"($LOCALNET_DIR)/logs" + + let args = (build-base-args $genesis_path $datadir $log_dir 8545 9001) + | append (build-dev-args) + | append (log-filter-args $loud) + | append $extra_args + + let cmd = wrap-samply [$tempo_bin ...$args] $samply $samply_args + print $"Running dev node: `($cmd | str join ' ')`..." + run-external ($cmd | first) ...($cmd | skip 1) +} + +# Build base node arguments shared between dev and consensus modes +def build-base-args [genesis_path: string, datadir: string, log_dir: string, http_port: int, reth_metrics_port: int] { + [ + "node" + "--chain" $genesis_path + "--datadir" $datadir + "--http" + "--http.addr" "0.0.0.0" + "--http.port" $"($http_port)" + "--http.api" "all" + "--metrics" $"0.0.0.0:($reth_metrics_port)" + "--log.file.directory" $log_dir + "--faucet.enabled" + "--faucet.private-key" "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" + "--faucet.amount" "1000000000000" + "--faucet.address" "0x20c0000000000000000000000000000000000000" + "--faucet.address" "0x20c0000000000000000000000000000000000001" + ] +} + +# Build dev mode specific arguments +def build-dev-args [] { + [ + "--dev" + "--dev.block-time" "1sec" + "--builder.gaslimit" "3000000000" + "--builder.max-tasks" "8" + "--builder.deadline" "3" + ] +} + +# ============================================================================ +# Consensus mode +# ============================================================================ + +def run-consensus-nodes [nodes: int, accounts: int, genesis: string, samply: bool, samply_args: list, reset: bool, profile: string, loud: bool, extra_args: list] { + # Check if we need to generate localnet (only if no custom genesis provided) + if $genesis == "" { + let needs_generation = $reset or (not ($LOCALNET_DIR | path exists)) or ( + (ls $LOCALNET_DIR | where type == "dir" | get name | where { |d| ($d | path basename) =~ '^\d+\.\d+\.\d+\.\d+:\d+$' } | length) == 0 + ) + + if $needs_generation { + if $reset { + print "Resetting localnet data..." + } else { + print "Localnet not found, generating..." + } + rm -rf $LOCALNET_DIR + + # Generate validator addresses (port 8000, 8100, 8200, ...) + # Using 100-port gaps to avoid collisions with system services (e.g., Intuit on 8021) + let validators = (0..<$nodes | each { |i| $"127.0.0.1:($i * 100 + 8000)" } | str join ",") + + print $"Generating localnet with ($accounts) accounts and ($nodes) validators..." + cargo run -p tempo-xtask --profile $profile -- generate-localnet -o $LOCALNET_DIR --accounts $accounts --validators $validators --force | ignore + } + } + + # Parse the generated node configs + let genesis_path = if $genesis != "" { $genesis } else { $"($LOCALNET_DIR)/genesis.json" } + + # Build trusted peers from enode.identity files + let validator_dirs = (ls $LOCALNET_DIR | where type == "dir" | get name | where { |d| ($d | path basename) =~ '^\d+\.\d+\.\d+\.\d+:\d+$' }) + let trusted_peers = ($validator_dirs | each { |d| + let addr = ($d | path basename) + let port = ($addr | split row ":" | get 1 | into int) + let identity = (open $"($d)/enode.identity" | str trim) + $"enode://($identity)@127.0.0.1:($port + 1)" + } | str join ",") + + print $"Found ($validator_dirs | length) validator configs" + + let tempo_bin = if $profile == "dev" { + "./target/debug/tempo" + } else { + $"./target/($profile)/tempo" + } + + # Start background nodes first (all except node 0) + print $"Starting ($validator_dirs | length) nodes..." + print $"Logs: ($LOGS_DIR)/" + print "Press Ctrl+C to stop all nodes." + + let foreground_node = $validator_dirs | first + let background_nodes = $validator_dirs | skip 1 + + for node in $background_nodes { + run-consensus-node $node $genesis_path $trusted_peers $tempo_bin $loud false [] $extra_args true + } + + # Run node 0 in foreground (receives Ctrl+C directly) + run-consensus-node $foreground_node $genesis_path $trusted_peers $tempo_bin $loud $samply $samply_args $extra_args false +} + +# Run a single consensus node (foreground or background) +def run-consensus-node [ + node_dir: string + genesis_path: string + trusted_peers: string + tempo_bin: string + loud: bool + samply: bool + samply_args: list + extra_args: list + background: bool +] { + let addr = ($node_dir | path basename) + let port = ($addr | split row ":" | get 1 | into int) + let node_index = (port-to-node-index $port) + let http_port = 8545 + $node_index + + let log_dir = $"($LOGS_DIR)/($addr)" + mkdir $log_dir + + let args = (build-consensus-node-args $node_dir $genesis_path $trusted_peers $port $log_dir) + | append (log-filter-args $loud) + | append $extra_args + + let cmd = wrap-samply [$tempo_bin ...$args] $samply $samply_args + + print $" Node ($addr) -> http://localhost:($http_port)(if $background { '' } else { ' (foreground)' })" + + if $background { + job spawn { sh -c $"($cmd | str join ' ') 2>&1" | lines | each { |line| print $"[($addr)] ($line)" } } + } else { + print $" Running: ($cmd | str join ' ')" + run-external ($cmd | first) ...($cmd | skip 1) + } +} + +# Build full node arguments for consensus mode +def build-consensus-node-args [node_dir: string, genesis_path: string, trusted_peers: string, port: int, log_dir: string] { + let node_index = (port-to-node-index $port) + let http_port = 8545 + $node_index + let reth_metrics_port = 9001 + $node_index + + (build-base-args $genesis_path $node_dir $log_dir $http_port $reth_metrics_port) + | append (build-consensus-args $node_dir $trusted_peers $port) +} + +# Build consensus mode specific arguments +def build-consensus-args [node_dir: string, trusted_peers: string, port: int] { + let signing_key = $"($node_dir)/signing.key" + let signing_share = $"($node_dir)/signing.share" + let enode_key = $"($node_dir)/enode.key" + + let execution_p2p_port = $port + 1 + let metrics_port = $port + 2 + let authrpc_port = $port + 3 + + [ + "--consensus.signing-key" $signing_key + "--consensus.signing-share" $signing_share + "--consensus.listen-address" $"127.0.0.1:($port)" + "--consensus.metrics-address" $"127.0.0.1:($metrics_port)" + "--trusted-peers" $trusted_peers + "--port" $"($execution_p2p_port)" + "--discovery.port" $"($execution_p2p_port)" + "--p2p-secret-key" $enode_key + "--authrpc.port" $"($authrpc_port)" + "--consensus.fee-recipient" "0x0000000000000000000000000000000000000000" + ] +} + +# ============================================================================ +# Bench command +# ============================================================================ + +# Run a full benchmark: start infra, localnet, and tempo-bench +def "main bench" [ + --mode: string = "consensus" # Mode: "dev" or "consensus" + --preset: string = "" # Preset: tip20, erc20, swap, order, tempo-mix + --tps: int = 10000 # Target TPS + --duration: int = 30 # Duration in seconds + --accounts: int = 1000 # Number of accounts + --max-concurrent-requests: int = 100 # Max concurrent requests + --nodes: int = 3 # Number of consensus nodes (consensus mode only) + --genesis: string = "" # Custom genesis file path (skips generation) + --samply # Profile nodes with samply + --samply-args: string = "" # Additional samply arguments (space-separated) + --reset # Reset localnet before starting + --loud # Show node logs (silent by default) + --profile: string = $DEFAULT_PROFILE # Cargo build profile + --features: string = $DEFAULT_FEATURES # Cargo features + --node-args: string = "" # Additional node arguments (space-separated) + --bench-args: string = "" # Additional tempo-bench arguments (space-separated) +] { + validate-mode $mode + + # Validate --nodes is only used with consensus mode + if $mode == "dev" and $nodes != 3 { + print "Error: --nodes is only valid with --mode consensus" + exit 1 + } + + # Validate: either preset or bench-args must be provided + if $preset == "" and $bench_args == "" { + print "Error: either --preset or --bench-args must be provided" + print $" Available presets: ($PRESETS | columns | str join ', ')" + exit 1 + } + + # Validate preset if provided + if $preset != "" and not ($preset in $PRESETS) { + print $"Unknown preset: ($preset). Available: ($PRESETS | columns | str join ', ')" + exit 1 + } + + let weights = if $preset != "" { $PRESETS | get $preset } else { [0.0, 0.0, 0.0, 0.0] } + + # Start observability stack + print "Starting observability stack..." + docker compose -f $"($BENCH_DIR)/docker-compose.yml" up -d + + # Build both binaries first + build-tempo ["tempo" "tempo-bench"] $profile $features + + # Start nodes in background (skip build since we already compiled) + let num_nodes = if $mode == "dev" { 1 } else { $nodes } + print $"Starting ($num_nodes) ($mode) node\(s\)..." + + # Ensure at least as many accounts as validators for genesis generation (+1 for admin account) + let genesis_accounts = ([$accounts $num_nodes] | math max) + 1 + + let node_cmd = [ + "nu" "tempo.nu" "localnet" + "--mode" $mode + "--accounts" $"($genesis_accounts)" + "--skip-build" + "--force" + "--profile" $profile + "--features" $features + ] + | append (if $mode == "consensus" { ["--nodes" $"($nodes)"] } else { [] }) + | append (if $genesis != "" { ["--genesis" $genesis] } else { [] }) + | append (if $reset { ["--reset"] } else { [] }) + | append (if $samply { ["--samply"] } else { [] }) + | append (if $samply_args != "" { [$"--samply-args=\"($samply_args)\""] } else { [] }) + | append (if $loud { ["--loud"] } else { [] }) + | append (if $node_args != "" { [$"--node-args=\"($node_args)\""] } else { [] }) + + # Spawn nodes as a background job (pipe output to show logs) + let node_cmd_str = ($node_cmd | str join " ") + print $" Command: ($node_cmd_str)" + job spawn { nu -c $node_cmd_str o+e>| lines | each { |line| print $line } } + + # Wait for nodes to be ready + sleep 2sec + print "Waiting for nodes to be ready..." + let rpc_urls = (0..<$num_nodes | each { |i| $"http://localhost:(8545 + $i)" }) + for url in $rpc_urls { + wait-for-rpc $url + } + print "All nodes ready!" + + # Run tempo-bench + let tempo_bench_bin = if $profile == "dev" { + "./target/debug/tempo-bench" + } else { + $"./target/($profile)/tempo-bench" + } + let bench_cmd = [ + $tempo_bench_bin + "run-max-tps" + "--tps" $"($tps)" + "--duration" $"($duration)" + "--accounts" $"($accounts)" + "--max-concurrent-requests" $"($max_concurrent_requests)" + "--target-urls" ($rpc_urls | str join ",") + "--faucet" + "--clear-txpool" + ] + | append (if $preset != "" { + [ + "--tip20-weight" $"($weights | get 0)" + "--erc20-weight" $"($weights | get 1)" + "--swap-weight" $"($weights | get 2)" + "--place-order-weight" $"($weights | get 3)" + ] + } else { [] }) + | append (if $bench_args != "" { $bench_args | split row " " } else { [] }) + + print $"Running benchmark: ($bench_cmd | str join ' ')" + try { + bash -c $"ulimit -Sn unlimited && ($bench_cmd | str join ' ')" + } catch { + print "Benchmark interrupted or failed." + } + + # Cleanup + print "Cleaning up..." + main kill + + # Wait for samply to finish saving profiles + if $samply { + print "Waiting for samply to finish..." + loop { + let samply_running = (ps | where name =~ "samply" | length) > 0 + if not $samply_running { + break + } + sleep 500ms + } + print "Samply profiles saved." + } + + print "Done." +} + +# Wait for an RPC endpoint to be ready and chain advancing +def wait-for-rpc [url: string, max_attempts: int = 120] { + mut attempt = 0 + mut start_block: int = -1 + + loop { + $attempt = $attempt + 1 + if $attempt > $max_attempts { + print $" Timeout waiting for ($url)" + exit 1 + } + let result = (do { cast block-number --rpc-url $url } | complete) + if $result.exit_code == 0 { + let block = ($result.stdout | str trim | into int) + if $start_block == -1 { + $start_block = $block + print $" ($url) connected \(block ($block)\), waiting for chain to advance..." + } else if $block > $start_block { + print $" ($url) ready \(block ($start_block) -> ($block)\)" + break + } else { + if ($attempt mod 10) == 0 { + print $" ($url) still at block ($block)... \(($attempt)s\)" + } + } + } else { + if ($attempt mod 10) == 0 { + print $" Still waiting for ($url)... \(($attempt)s\)" + } + } + sleep 1sec + } +} + +# ============================================================================ +# Help +# ============================================================================ + +# Show help +def main [] { + print "Tempo local utilities" + print "" + print "Usage:" + print " nu tempo.nu bench [flags] Run full benchmark (infra + localnet + bench)" + print " nu tempo.nu localnet [flags] Run Tempo localnet" + print " nu tempo.nu infra up Start Grafana + Prometheus" + print " nu tempo.nu infra down Stop the observability stack" + print " nu tempo.nu kill Kill any running tempo processes" + print "" + print "Bench flags (either --preset or --bench-args required):" + print " --mode Mode: dev or consensus (default: consensus)" + print " --preset

Preset: tip20, erc20, swap, order, tempo-mix" + print " --tps Target TPS (default: 10000)" + print " --duration Duration in seconds (default: 30)" + print " --accounts Number of accounts (default: 1000)" + print " --max-concurrent-requests Max concurrent requests (default: 100)" + print " --nodes Number of consensus nodes (default: 3, consensus mode only)" + print " --samply Profile nodes with samply" + print " --samply-args Additional samply arguments (space-separated)" + print " --reset Reset localnet before starting" + print " --loud Show all node logs (WARN/ERROR shown by default)" + print $" --profile

Cargo profile \(default: ($DEFAULT_PROFILE)\)" + print $" --features Cargo features \(default: ($DEFAULT_FEATURES)\)" + print " --node-args Additional node arguments (space-separated)" + print " --bench-args Additional tempo-bench arguments (space-separated)" + print "" + print "Localnet flags:" + print " --mode Mode (default: dev)" + print " --nodes Number of validators for consensus (default: 3)" + print " --accounts Genesis accounts (default: 1000)" + print " --samply Enable samply profiling (foreground node only)" + print " --samply-args Additional samply arguments (space-separated)" + print " --loud Show all node logs (WARN/ERROR shown by default)" + print " --reset Wipe and regenerate localnet" + print $" --profile

Cargo profile \(default: ($DEFAULT_PROFILE)\)" + print $" --features Cargo features \(default: ($DEFAULT_FEATURES)\)" + print " --node-args Additional node arguments (space-separated)" + print "" + print "Examples:" + print " nu tempo.nu bench --preset tip20 --tps 20000 --duration 60" + print " nu tempo.nu bench --preset tempo-mix --tps 5000 --samply --reset" + print " nu tempo.nu infra up" + print " nu tempo.nu localnet --mode dev --samply --accounts 50000 --reset" + print " nu tempo.nu localnet --mode consensus --nodes 3" + print "" + print "Port assignments (consensus mode, per node N=0,1,2...):" + print " Consensus: 8000 + N*100" + print " P2P: 8001 + N*100" + print " Metrics: 8002 + N*100" + print " AuthRPC: 8003 + N*100" + print " HTTP RPC: 8545 + N" + print " Reth Metrics: 9001 + N" +} From c5d797515b551a342bab60eb46ac80a0447f6704 Mon Sep 17 00:00:00 2001 From: Derek Cofausper <256792747+decofe@users.noreply.github.com> Date: Fri, 3 Apr 2026 18:14:07 +0000 Subject: [PATCH 02/12] fix: add bouncebackRecipient to all deposit() and depositEncrypted() call sites Updates the Rust ABI binding and all callers to include the new bouncebackRecipient parameter added by the bounceback spec. Co-Authored-By: dankrad <6130607+dankrad@users.noreply.github.com> Amp-Thread-ID: https://ampcode.com/threads/T-019d5473-3933-756c-8b65-60dfe41cb262 --- crates/primitives/src/abi.rs | 5 +++-- crates/tempo-zone/tests/it/deposit.rs | 2 +- crates/tempo-zone/tests/it/l1_e2e.rs | 4 +++- crates/tempo-zone/tests/it/utils.rs | 5 +++-- xtask/src/demo_blacklist.rs | 6 +++--- xtask/src/demo_swap_and_deposit.rs | 3 ++- xtask/src/encrypted_deposit.rs | 2 +- xtask/src/spam_deposits.rs | 2 ++ 8 files changed, 18 insertions(+), 11 deletions(-) diff --git a/crates/primitives/src/abi.rs b/crates/primitives/src/abi.rs index 448910513..799c50f6b 100644 --- a/crates/primitives/src/abi.rs +++ b/crates/primitives/src/abi.rs @@ -214,7 +214,7 @@ macro_rules! define_abi { // -- State-changing functions -- - function deposit(address token, address to, uint128 amount, bytes32 memo) + function deposit(address token, address to, uint128 amount, bytes32 memo, address bouncebackRecipient) external returns (bytes32 newCurrentDepositQueueHash); @@ -236,7 +236,8 @@ macro_rules! define_abi { address token, uint128 amount, uint256 keyIndex, - EncryptedDepositPayload calldata encrypted + EncryptedDepositPayload calldata encrypted, + address bouncebackRecipient ) external returns (bytes32 newCurrentDepositQueueHash); function setSequencerEncryptionKey( diff --git a/crates/tempo-zone/tests/it/deposit.rs b/crates/tempo-zone/tests/it/deposit.rs index a3f7cd083..cd4fbb4be 100644 --- a/crates/tempo-zone/tests/it/deposit.rs +++ b/crates/tempo-zone/tests/it/deposit.rs @@ -123,7 +123,7 @@ async fn test_l1_deposit_mints_on_zone() -> eyre::Result<()> { // Execute deposit on L1 let deposit_receipt = portal - .deposit(l1_token_address, recipient, deposit_amount, B256::ZERO) + .deposit(l1_token_address, recipient, deposit_amount, B256::ZERO, Address::ZERO) .send() .await? .get_receipt() diff --git a/crates/tempo-zone/tests/it/l1_e2e.rs b/crates/tempo-zone/tests/it/l1_e2e.rs index 9039d0381..33e5ae255 100644 --- a/crates/tempo-zone/tests/it/l1_e2e.rs +++ b/crates/tempo-zone/tests/it/l1_e2e.rs @@ -1128,6 +1128,7 @@ async fn test_encrypted_deposit_blacklisted_recipient() -> eyre::Result<()> { nonce: alloy_primitives::FixedBytes(enc.nonce), tag: alloy_primitives::FixedBytes(enc.tag), }, + Address::ZERO, ) .send() .await? @@ -1249,7 +1250,7 @@ async fn test_blacklisted_sender_transfer_rejected() -> eyre::Result<()> { let portal = ZonePortal::new(portal_address, &dev_provider); let receipt = portal - .deposit(PATH_USD_ADDRESS, alice, deposit_amount, B256::ZERO) + .deposit(PATH_USD_ADDRESS, alice, deposit_amount, B256::ZERO, Address::ZERO) .send() .await? .get_receipt() @@ -1364,6 +1365,7 @@ async fn test_deposit_to_blacklisted_recipient_reverts_on_l1() -> eyre::Result<( blacklisted_recipient, deposit_amount, B256::ZERO, + Address::ZERO, ) .send() .await; diff --git a/crates/tempo-zone/tests/it/utils.rs b/crates/tempo-zone/tests/it/utils.rs index 71651e568..9f68a88bb 100644 --- a/crates/tempo-zone/tests/it/utils.rs +++ b/crates/tempo-zone/tests/it/utils.rs @@ -1931,7 +1931,7 @@ impl ZoneAccount { let portal = ZonePortal::new(self.portal_address, &self.l1_provider); let receipt = portal - .deposit(PATH_USD_ADDRESS, recipient, amount, B256::ZERO) + .deposit(PATH_USD_ADDRESS, recipient, amount, B256::ZERO, Address::ZERO) .send() .await? .get_receipt() @@ -1986,7 +1986,7 @@ impl ZoneAccount { let portal = ZonePortal::new(self.portal_address, &self.l1_provider); let receipt = portal - .deposit(token, self.address, amount, B256::ZERO) + .deposit(token, self.address, amount, B256::ZERO, Address::ZERO) .send() .await? .get_receipt() @@ -2091,6 +2091,7 @@ impl ZoneAccount { nonce: alloy_primitives::FixedBytes(enc.nonce), tag: alloy_primitives::FixedBytes(enc.tag), }, + Address::ZERO, ) .send() .await? diff --git a/xtask/src/demo_blacklist.rs b/xtask/src/demo_blacklist.rs index db9649f7d..410c42170 100644 --- a/xtask/src/demo_blacklist.rs +++ b/xtask/src/demo_blacklist.rs @@ -329,7 +329,7 @@ impl DemoBlacklist { let mut pending = None; for attempt in 0..5u32 { match portal - .deposit(token_addr, admin, deposit_amount, B256::ZERO) + .deposit(token_addr, admin, deposit_amount, B256::ZERO, Address::ZERO) .send() .await { @@ -467,7 +467,7 @@ impl DemoBlacklist { let gas_fund: u128 = 100_000; let l2_block_before = l2.get_block_number().await.unwrap_or(0); let receipt = portal - .deposit(PATH_USD_ADDRESS, target, gas_fund, B256::ZERO) + .deposit(PATH_USD_ADDRESS, target, gas_fund, B256::ZERO, Address::ZERO) .send_sync() .await?; check(&receipt, "deposit pathUSD to target for gas")?; @@ -646,7 +646,7 @@ async fn send_encrypted_deposit>( }; let receipt = portal - .depositEncrypted(token, amount, key_index, payload) + .depositEncrypted(token, amount, key_index, payload, Address::ZERO) .send_sync() .await .wrap_err("depositEncrypted send failed")?; diff --git a/xtask/src/demo_swap_and_deposit.rs b/xtask/src/demo_swap_and_deposit.rs index c2861cfeb..e36c073a4 100644 --- a/xtask/src/demo_swap_and_deposit.rs +++ b/xtask/src/demo_swap_and_deposit.rs @@ -264,6 +264,7 @@ impl DemoSwapAndDeposit { operator, pathusd_gross_deposit, B256::ZERO, + Address::ZERO, ) .send_sync() .await @@ -279,7 +280,7 @@ impl DemoSwapAndDeposit { .await .wrap_err("failed to approve AlphaUSD for portal")?; let receipt = portal_contract - .deposit(alpha, operator, alpha_gross_deposit, B256::ZERO) + .deposit(alpha, operator, alpha_gross_deposit, B256::ZERO, Address::ZERO) .send_sync() .await .wrap_err("failed to deposit AlphaUSD to the zone")?; diff --git a/xtask/src/encrypted_deposit.rs b/xtask/src/encrypted_deposit.rs index d4f215acb..9a7154cd2 100644 --- a/xtask/src/encrypted_deposit.rs +++ b/xtask/src/encrypted_deposit.rs @@ -117,7 +117,7 @@ impl EncryptedDeposit { println!("Sending encrypted deposit of {} to {to}...", self.amount); let receipt = portal - .depositEncrypted(self.token, self.amount, key_index, payload) + .depositEncrypted(self.token, self.amount, key_index, payload, Address::ZERO) .send_sync() .await .wrap_err("failed to send depositEncrypted transaction")?; diff --git a/xtask/src/spam_deposits.rs b/xtask/src/spam_deposits.rs index b4218cb0b..232b8637b 100644 --- a/xtask/src/spam_deposits.rs +++ b/xtask/src/spam_deposits.rs @@ -323,6 +323,7 @@ impl SpamDeposits { amount: self.amount, keyIndex: key_index, encrypted: payload, + bouncebackRecipient: Address::ZERO, } .abi_encode()) } else { @@ -331,6 +332,7 @@ impl SpamDeposits { to: recipient, amount: self.amount, memo: B256::ZERO, + bouncebackRecipient: Address::ZERO, } .abi_encode()) } From bb3f9c4c107f01d11e5a54d58ffcc3020fe866e4 Mon Sep 17 00:00:00 2001 From: Derek Cofausper <256792747+decofe@users.noreply.github.com> Date: Sun, 5 Apr 2026 21:03:19 +0000 Subject: [PATCH 03/12] fix: rustfmt formatting and regenerate zone-test-genesis with outbox arg - Format .deposit() calls to multi-line across 5 files (cargo fmt) - Pass ZONE_OUTBOX_ADDRESS as 4th arg to ZoneInbox constructor in generate_zone_genesis.rs (was missing after Solidity constructor update) - Regenerate zone-test-genesis.json with updated ZoneInbox bytecode Co-authored-by: dankrad <6130607+dankrad@users.noreply.github.com> Amp-Thread-ID: https://ampcode.com/threads/T-019d5f52-e187-7554-b95f-59c7b789eb28 --- .../tests/assets/zone-test-genesis.json | 140 +++++++++++++++++- crates/tempo-zone/tests/it/deposit.rs | 8 +- crates/tempo-zone/tests/it/l1_e2e.rs | 8 +- crates/tempo-zone/tests/it/utils.rs | 16 +- xtask/src/demo_blacklist.rs | 16 +- xtask/src/demo_swap_and_deposit.rs | 8 +- xtask/src/generate_zone_genesis.rs | 9 +- 7 files changed, 195 insertions(+), 10 deletions(-) diff --git a/crates/tempo-zone/tests/assets/zone-test-genesis.json b/crates/tempo-zone/tests/assets/zone-test-genesis.json index 160e1313d..f450e9a76 100644 --- a/crates/tempo-zone/tests/assets/zone-test-genesis.json +++ b/crates/tempo-zone/tests/assets/zone-test-genesis.json @@ -1 +1,139 @@ -{"config":{"chainId":1337,"homesteadBlock":0,"daoForkSupport":false,"eip150Block":0,"eip155Block":0,"eip158Block":0,"byzantiumBlock":0,"constantinopleBlock":0,"petersburgBlock":0,"istanbulBlock":0,"berlinBlock":0,"londonBlock":0,"mergeNetsplitBlock":0,"shanghaiTime":0,"cancunTime":0,"pragueTime":0,"osakaTime":0,"terminalTotalDifficulty":0,"terminalTotalDifficultyPassed":true,"depositContractAddress":"0x0000000000000000000000000000000000000000"},"nonce":"0x42","timestamp":"0x0","extraData":"0x74656d706f2d7a6f6e652d67656e65736973","gasLimit":"0x1c9c380","difficulty":"0x0","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","coinbase":"0x0000000000000000000000000000000000000000","alloc":{"0x0000000000000000000000000000000000000000":{"nonce":"0x1","balance":"0x0"},"0x000000000022d473030f116ddee9f6b43ac78ba3":{"nonce":"0x1","balance":"0x0","code":"0x6040608081526004908136101561001557600080fd5b600090813560e01c80630d58b1db1461126c578063137c29fe146110755780632a2d80d114610db75780632b67b57014610bde57806330f28b7a14610ade5780633644e51514610a9d57806336c7851614610a285780633ff9dcb1146109a85780634fe02b441461093f57806365d9723c146107ac57806387517c451461067a578063927da105146105c3578063cc53287f146104a3578063edd9444b1461033a5763fe8ec1a7146100c657600080fd5b346103365760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103365767ffffffffffffffff833581811161033257610114903690860161164b565b60243582811161032e5761012b903690870161161a565b6101336114e6565b9160843585811161032a5761014b9036908a016115c1565b98909560a43590811161032657610164913691016115c1565b969095815190610173826113ff565b606b82527f5065726d697442617463685769746e6573735472616e7366657246726f6d285460208301527f6f6b656e5065726d697373696f6e735b5d207065726d69747465642c61646472838301527f657373207370656e6465722c75696e74323536206e6f6e63652c75696e74323560608301527f3620646561646c696e652c000000000000000000000000000000000000000000608083015282519a8b9181610222602085018096611f93565b918237018a8152039961025b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09b8c8101835282611437565b5190209085515161026b81611ebb565b908a5b8181106102f95750506102f6999a6102ed9183516102a081610294602082018095611f66565b03848101835282611437565b519020602089810151858b015195519182019687526040820192909252336060820152608081019190915260a081019390935260643560c08401528260e081015b03908101835282611437565b51902093611cf7565b80f35b8061031161030b610321938c5161175e565b51612054565b61031b828661175e565b52611f0a565b61026e565b8880fd5b8780fd5b8480fd5b8380fd5b5080fd5b5091346103365760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103365767ffffffffffffffff9080358281116103325761038b903690830161164b565b60243583811161032e576103a2903690840161161a565b9390926103ad6114e6565b9160643590811161049f576103c4913691016115c1565b949093835151976103d489611ebb565b98885b81811061047d5750506102f697988151610425816103f9602082018095611f66565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282611437565b5190206020860151828701519083519260208401947ffcf35f5ac6a2c28868dc44c302166470266239195f02b0ee408334829333b7668652840152336060840152608083015260a082015260a081526102ed8161141b565b808b61031b8261049461030b61049a968d5161175e565b9261175e565b6103d7565b8680fd5b5082346105bf57602090817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103325780359067ffffffffffffffff821161032e576104f49136910161161a565b929091845b848110610504578580f35b8061051a610515600193888861196c565b61197c565b61052f84610529848a8a61196c565b0161197c565b3389528385528589209173ffffffffffffffffffffffffffffffffffffffff80911692838b528652868a20911690818a5285528589207fffffffffffffffffffffffff000000000000000000000000000000000000000081541690558551918252848201527f89b1add15eff56b3dfe299ad94e01f2b52fbcb80ae1a3baea6ae8c04cb2b98a4853392a2016104f9565b8280fd5b50346103365760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033657610676816105ff6114a0565b936106086114c3565b6106106114e6565b73ffffffffffffffffffffffffffffffffffffffff968716835260016020908152848420928816845291825283832090871683528152919020549251938316845260a083901c65ffffffffffff169084015260d09190911c604083015281906060820190565b0390f35b50346103365760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610336576106b26114a0565b906106bb6114c3565b916106c46114e6565b65ffffffffffff926064358481169081810361032a5779ffffffffffff0000000000000000000000000000000000000000947fda9fa7c1b00402c17d0161b249b1ab8bbec047c5a52207b9c112deffd817036b94338a5260016020527fffffffffffff0000000000000000000000000000000000000000000000000000858b209873ffffffffffffffffffffffffffffffffffffffff809416998a8d5260205283878d209b169a8b8d52602052868c209486156000146107a457504216925b8454921697889360a01b16911617179055815193845260208401523392a480f35b905092610783565b5082346105bf5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf576107e56114a0565b906107ee6114c3565b9265ffffffffffff604435818116939084810361032a57338852602091600183528489209673ffffffffffffffffffffffffffffffffffffffff80911697888b528452858a20981697888a5283528489205460d01c93848711156109175761ffff9085840316116108f05750907f55eb90d810e1700b35a8e7e25395ff7f2b2259abd7415ca2284dfb1c246418f393929133895260018252838920878a528252838920888a5282528389209079ffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffff000000000000000000000000000000000000000000000000000083549260d01b16911617905582519485528401523392a480f35b84517f24d35a26000000000000000000000000000000000000000000000000000000008152fd5b5084517f756688fe000000000000000000000000000000000000000000000000000000008152fd5b503461033657807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610336578060209273ffffffffffffffffffffffffffffffffffffffff61098f6114a0565b1681528084528181206024358252845220549051908152f35b5082346105bf57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf577f3704902f963766a4e561bbaab6e6cdc1b1dd12f6e9e99648da8843b3f46b918d90359160243533855284602052818520848652602052818520818154179055815193845260208401523392a280f35b8234610a9a5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a9a57610a606114a0565b610a686114c3565b610a706114e6565b6064359173ffffffffffffffffffffffffffffffffffffffff8316830361032e576102f6936117a1565b80fd5b503461033657817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033657602090610ad7611b1e565b9051908152f35b508290346105bf576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf57610b1a3661152a565b90807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c36011261033257610b4c611478565b9160e43567ffffffffffffffff8111610bda576102f694610b6f913691016115c1565b939092610b7c8351612054565b6020840151828501519083519260208401947f939c21a48a8dbe3a9a2404a1d46691e4d39f6583d6ec6b35714604c986d801068652840152336060840152608083015260a082015260a08152610bd18161141b565b51902091611c25565b8580fd5b509134610336576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033657610c186114a0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc360160c08112610332576080855191610c51836113e3565b1261033257845190610c6282611398565b73ffffffffffffffffffffffffffffffffffffffff91602435838116810361049f578152604435838116810361049f57602082015265ffffffffffff606435818116810361032a5788830152608435908116810361049f576060820152815260a435938285168503610bda576020820194855260c4359087830182815260e43567ffffffffffffffff811161032657610cfe90369084016115c1565b929093804211610d88575050918591610d786102f6999a610d7e95610d238851611fbe565b90898c511690519083519260208401947ff3841cd1ff0085026a6327b620b67997ce40f282c88a8e905a7a5626e310f3d086528401526060830152608082015260808152610d70816113ff565b519020611bd9565b916120c7565b519251169161199d565b602492508a51917fcd21db4f000000000000000000000000000000000000000000000000000000008352820152fd5b5091346103365760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc93818536011261033257610df36114a0565b9260249081359267ffffffffffffffff9788851161032a578590853603011261049f578051978589018981108282111761104a578252848301358181116103265785019036602383011215610326578382013591610e50836115ef565b90610e5d85519283611437565b838252602093878584019160071b83010191368311611046578801905b828210610fe9575050508a526044610e93868801611509565b96838c01978852013594838b0191868352604435908111610fe557610ebb90369087016115c1565b959096804211610fba575050508998995151610ed681611ebb565b908b5b818110610f9757505092889492610d7892610f6497958351610f02816103f98682018095611f66565b5190209073ffffffffffffffffffffffffffffffffffffffff9a8b8b51169151928551948501957faf1b0d30d2cab0380e68f0689007e3254993c596f2fdd0aaa7f4d04f794408638752850152830152608082015260808152610d70816113ff565b51169082515192845b848110610f78578580f35b80610f918585610f8b600195875161175e565b5161199d565b01610f6d565b80610311610fac8e9f9e93610fb2945161175e565b51611fbe565b9b9a9b610ed9565b8551917fcd21db4f000000000000000000000000000000000000000000000000000000008352820152fd5b8a80fd5b6080823603126110465785608091885161100281611398565b61100b85611509565b8152611018838601611509565b838201526110278a8601611607565b8a8201528d611037818701611607565b90820152815201910190610e7a565b8c80fd5b84896041867f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5082346105bf576101407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf576110b03661152a565b91807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c360112610332576110e2611478565b67ffffffffffffffff93906101043585811161049f5761110590369086016115c1565b90936101243596871161032a57611125610bd1966102f6983691016115c1565b969095825190611134826113ff565b606482527f5065726d69745769746e6573735472616e7366657246726f6d28546f6b656e5060208301527f65726d697373696f6e73207065726d69747465642c6164647265737320737065848301527f6e6465722c75696e74323536206e6f6e63652c75696e7432353620646561646c60608301527f696e652c0000000000000000000000000000000000000000000000000000000060808301528351948591816111e3602085018096611f93565b918237018b8152039361121c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe095868101835282611437565b5190209261122a8651612054565b6020878101518589015195519182019687526040820192909252336060820152608081019190915260a081019390935260e43560c08401528260e081016102e1565b5082346105bf576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033257813567ffffffffffffffff92838211610bda5736602383011215610bda5781013592831161032e576024906007368386831b8401011161049f57865b8581106112e5578780f35b80821b83019060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc83360301126103265761139288876001946060835161132c81611398565b611368608461133c8d8601611509565b9485845261134c60448201611509565b809785015261135d60648201611509565b809885015201611509565b918291015273ffffffffffffffffffffffffffffffffffffffff80808093169516931691166117a1565b016112da565b6080810190811067ffffffffffffffff8211176113b457604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff8211176113b457604052565b60a0810190811067ffffffffffffffff8211176113b457604052565b60c0810190811067ffffffffffffffff8211176113b457604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176113b457604052565b60c4359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b600080fd5b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b6044359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc01906080821261149b576040805190611563826113e3565b8082941261149b57805181810181811067ffffffffffffffff8211176113b457825260043573ffffffffffffffffffffffffffffffffffffffff8116810361149b578152602435602082015282526044356020830152606435910152565b9181601f8401121561149b5782359167ffffffffffffffff831161149b576020838186019501011161149b57565b67ffffffffffffffff81116113b45760051b60200190565b359065ffffffffffff8216820361149b57565b9181601f8401121561149b5782359167ffffffffffffffff831161149b576020808501948460061b01011161149b57565b91909160608184031261149b576040805191611666836113e3565b8294813567ffffffffffffffff9081811161149b57830182601f8201121561149b578035611693816115ef565b926116a087519485611437565b818452602094858086019360061b8501019381851161149b579086899897969594939201925b8484106116e3575050505050855280820135908501520135910152565b90919293949596978483031261149b578851908982019082821085831117611730578a928992845261171487611509565b81528287013583820152815201930191908897969594936116c6565b602460007f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b80518210156117725760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b92919273ffffffffffffffffffffffffffffffffffffffff604060008284168152600160205282828220961695868252602052818120338252602052209485549565ffffffffffff8760a01c16804211611884575082871696838803611812575b5050611810955016926118b5565b565b878484161160001461184f57602488604051907ff96fb0710000000000000000000000000000000000000000000000000000000082526004820152fd5b7fffffffffffffffffffffffff000000000000000000000000000000000000000084846118109a031691161790553880611802565b602490604051907fd81b2f2e0000000000000000000000000000000000000000000000000000000082526004820152fd5b9060006064926020958295604051947f23b872dd0000000000000000000000000000000000000000000000000000000086526004860152602485015260448401525af13d15601f3d116001600051141617161561190e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152fd5b91908110156117725760061b0190565b3573ffffffffffffffffffffffffffffffffffffffff8116810361149b5790565b9065ffffffffffff908160608401511673ffffffffffffffffffffffffffffffffffffffff908185511694826020820151169280866040809401511695169560009187835260016020528383208984526020528383209916988983526020528282209184835460d01c03611af5579185611ace94927fc6a377bfc4eb120024a8ac08eef205be16b817020812c73223e81d1bdb9708ec98979694508715600014611ad35779ffffffffffff00000000000000000000000000000000000000009042165b60a01b167fffffffffffff00000000000000000000000000000000000000000000000000006001860160d01b1617179055519384938491604091949373ffffffffffffffffffffffffffffffffffffffff606085019616845265ffffffffffff809216602085015216910152565b0390a4565b5079ffffffffffff000000000000000000000000000000000000000087611a60565b600484517f756688fe000000000000000000000000000000000000000000000000000000008152fd5b467f000000000000000000000000000000000000000000000000000000000000053903611b69577f1f520b5ee38ad937955892c3dfc7055e8eeb515d905781b6951e4c687917c53090565b60405160208101907f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86682527f9ac997416e8ff9d2ff6bebeb7149f65cdae5e32e2b90440b566bb3044041d36a604082015246606082015230608082015260808152611bd3816113ff565b51902090565b611be1611b1e565b906040519060208201927f190100000000000000000000000000000000000000000000000000000000000084526022830152604282015260428152611bd381611398565b9192909360a435936040840151804211611cc65750602084510151808611611c955750918591610d78611c6594611c60602088015186611e47565b611bd9565b73ffffffffffffffffffffffffffffffffffffffff809151511692608435918216820361149b57611810936118b5565b602490604051907f3728b83d0000000000000000000000000000000000000000000000000000000082526004820152fd5b602490604051907fcd21db4f0000000000000000000000000000000000000000000000000000000082526004820152fd5b959093958051519560409283830151804211611e175750848803611dee57611d2e918691610d7860209b611c608d88015186611e47565b60005b868110611d42575050505050505050565b611d4d81835161175e565b5188611d5a83878a61196c565b01359089810151808311611dbe575091818888886001968596611d84575b50505050505001611d31565b611db395611dad9273ffffffffffffffffffffffffffffffffffffffff6105159351169561196c565b916118b5565b803888888883611d78565b6024908651907f3728b83d0000000000000000000000000000000000000000000000000000000082526004820152fd5b600484517fff633a38000000000000000000000000000000000000000000000000000000008152fd5b6024908551907fcd21db4f0000000000000000000000000000000000000000000000000000000082526004820152fd5b9073ffffffffffffffffffffffffffffffffffffffff600160ff83161b9216600052600060205260406000209060081c6000526020526040600020818154188091551615611e9157565b60046040517f756688fe000000000000000000000000000000000000000000000000000000008152fd5b90611ec5826115ef565b611ed26040519182611437565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611f0082946115ef565b0190602036910137565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611f375760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b805160208092019160005b828110611f7f575050505090565b835185529381019392810192600101611f71565b9081519160005b838110611fab575050016000815290565b8060208092840101518185015201611f9a565b60405160208101917f65626cad6cb96493bf6f5ebea28756c966f023ab9e8a83a7101849d5573b3678835273ffffffffffffffffffffffffffffffffffffffff8082511660408401526020820151166060830152606065ffffffffffff9182604082015116608085015201511660a082015260a0815260c0810181811067ffffffffffffffff8211176113b45760405251902090565b6040516020808201927f618358ac3db8dc274f0cd8829da7e234bd48cd73c4a740aede1adec9846d06a1845273ffffffffffffffffffffffffffffffffffffffff81511660408401520151606082015260608152611bd381611398565b919082604091031261149b576020823592013590565b6000843b61222e5750604182036121ac576120e4828201826120b1565b939092604010156117725760209360009360ff6040608095013560f81c5b60405194855216868401526040830152606082015282805260015afa156121a05773ffffffffffffffffffffffffffffffffffffffff806000511691821561217657160361214c57565b60046040517f815e1d64000000000000000000000000000000000000000000000000000000008152fd5b60046040517f8baa579f000000000000000000000000000000000000000000000000000000008152fd5b6040513d6000823e3d90fd5b60408203612204576121c0918101906120b1565b91601b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84169360ff1c019060ff8211611f375760209360009360ff608094612102565b60046040517f4be6321b000000000000000000000000000000000000000000000000000000008152fd5b929391601f928173ffffffffffffffffffffffffffffffffffffffff60646020957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0604051988997889687947f1626ba7e000000000000000000000000000000000000000000000000000000009e8f8752600487015260406024870152816044870152868601378b85828601015201168101030192165afa9081156123a857829161232a575b507fffffffff000000000000000000000000000000000000000000000000000000009150160361230057565b60046040517fb0669cbc000000000000000000000000000000000000000000000000000000008152fd5b90506020813d82116123a0575b8161234460209383611437565b810103126103365751907fffffffff0000000000000000000000000000000000000000000000000000000082168203610a9a57507fffffffff0000000000000000000000000000000000000000000000000000000090386122d4565b3d9150612337565b6040513d84823e3d90fdfea164736f6c6343000811000a"},"0x1c00000000000000000000000000000000000000":{"nonce":"0x1","balance":"0x0","code":"0x60806040526004361015610011575f80fd5b5f3560e01c80631d04645f146101245780632245d0831461011f5780632e224dee1461011a5780633d7a27611461011557806346903867146101105780634732f8bb1461010b57806352d922a51461010657806358c3659914610101578063615cf854146100fc5780636aba6931146100f757806380a4cbc8146100f257806381e3da6b146100ed5780639a7361eb146100e8578063c334cd20146100e3578063f3b52855146100de578063f495be0b146100d95763fe770099146100d4575f80fd5b61052e565b610505565b6104dc565b6104bf565b6104a2565b610345565b610329565b6102b1565b61023a565b610214565b6101f7565b6101d1565b6101b1565b610194565b610177565b61014e565b3461014a575f36600319011261014a5760206001600160401b0360075416604051908152f35b5f80fd5b3461014a575f36600319011261014a5760206001600160401b0360015460401c16604051908152f35b3461014a575f36600319011261014a576020600454604051908152f35b3461014a575f36600319011261014a576020600954604051908152f35b3461014a575f36600319011261014a57602060075460c01c604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360085416604051908152f35b3461014a575f36600319011261014a576020600254604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360015416604051908152f35b3461014a575f36600319011261014a576003546040516001600160a01b039091168152602090f35b600435906001600160a01b038216820361014a57565b60206040818301928281528451809452019201905f5b81811061029b5750505090565b825184526020938401939092019160010161028e565b3461014a57604036600319011261014a576102ca610262565b6024356001600160401b03811161014a573660238201121561014a5780600401356001600160401b03811161014a573660248260051b8401011161014a57610325926024610319930190610655565b60405191829182610278565b0390f35b3461014a575f36600319011261014a5760205f54604051908152f35b3461014a57604036600319011261014a5761035e610262565b3360016007609a1b01141580610491575b80610480575b61041557600754604051631e7d027560e31b81526001600160a01b03909216600483015260248035908301526001600160401b0316604482015260208160648160046007609a1b015afa801561041057610325915f916103e1575b506040519081529081906020820190565b610403915060203d602011610409575b6103fb8183610742565b8101906107f6565b5f6103d0565b503d6103f1565b6107eb565b60405162461bcd60e51b815260206004820152603b60248201527f54656d706f53746174653a206f6e6c79207a6f6e652073797374656d20636f6e60448201527f7472616374732063616e20726561642054656d706f20737461746500000000006064820152608490fd5b503360036007609a1b011415610375565b503360026007609a1b01141561036f565b3461014a575f36600319011261014a576020600554604051908152f35b3461014a575f36600319011261014a576020600654604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360075460401c16604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360075460801c16604051908152f35b3461014a57602036600319011261014a576004356001600160401b03811161014a573660238201121561014a578060040135906001600160401b03821161014a57366024838301011161014a576007609a1b193301610646576105b26105ad5f54926105a26007546001600160401b031690565b946024369201610805565b6108c6565b60025403610637576001600160401b036105ec6105e06105da6007546001600160401b031690565b9361085e565b6001600160401b031690565b9116908103610628575f546004546040519081527fdd85219569c3c880f014955916f426d1ca039714b59ce33e24f151f155ac26b990602090a3005b631391e11b60e21b5f5260045ffd5b63591c836760e01b5f5260045ffd5b6303300c7360e31b5f5260045ffd5b91903360016007609a1b0114158061071d575b8061070c575b61041557600754604051632593f8c960e01b81526001600160a01b03909416600485015260606024850152606484018390526001600160401b03166001600160fb1b03831161014a578380926084925f9560051b8092858501376044830152810103018160046007609a1b015afa908115610410575f916106ed575090565b61070991503d805f833e6107018183610742565b810190610768565b90565b503360036007609a1b01141561066e565b503360026007609a1b011415610668565b634e487b7160e01b5f52604160045260245ffd5b90601f801991011681019081106001600160401b0382111761076357604052565b61072e565b60208183031261014a578051906001600160401b03821161014a57019080601f8301121561014a578151916001600160401b038311610763578260051b90604051936107b76020840186610742565b845260208085019282010192831161014a57602001905b8282106107db5750505090565b81518152602091820191016107ce565b6040513d5f823e3d90fd5b9081602091031261014a575190565b9291926001600160401b038211610763576040519161082e601f8201601f191660200184610742565b82948184528183011161014a578281602093845f960137010152565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b036001911601906001600160401b03821161087c57565b61084a565b906001820180921161087c57565b600101908160011161087c57565b906021820180921161087c57565b906015820180921161087c57565b9190820180921161087c57565b805160208201205f556108d881610c28565b80915015610ba85761098b61095a61091c836109166108fa6109939688610dd1565b6001600160401b03166001600160401b03196001541617600155565b85610ea6565b905061095461092b8287610dd1565b67ffffffffffffffff60401b6001549160401b169067ffffffffffffffff60401b191617600155565b84610ea6565b90506109856109698286610dd1565b6001600160401b03166001600160401b03196008541617600855565b83610ea6565b905082610d0e565b91908215610ba857610b77610b6f610b5b610b53610b1f610add610aa5610a74610a6c610a648b610a5e610a598f610a3c610a286109f16109e9846109e36109de610a50978b611020565b600255565b88610ea6565b905087610ea6565b9050610a22610a0082896110f0565b60018060a01b03166bffffffffffffffffffffffff60a01b6003541617600355565b86610ea6565b9050610916610a378288611020565b600455565b9050610954610a4b8287611020565b600555565b93849150611020565b600655565b8c610ea6565b90508b610ea6565b90508a610ea6565b9050610a9f610a83828c610dd1565b6001600160401b03166001600160401b03196007541617600755565b89610ea6565b90506109e3610ab4828b610dd1565b67ffffffffffffffff60401b6007549160401b169067ffffffffffffffff60401b191617600755565b9050610b19610aec828a610dd1565b6007805467ffffffffffffffff60801b191660809290921b67ffffffffffffffff60801b16919091179055565b87610ea6565b9050610a22610b2e8289610dd1565b600780546001600160c01b031660c09290921b6001600160c01b031916919091179055565b905085610ea6565b9050610954610b6a8287611020565b600955565b905083610ea6565b9050905b610b8581856108b9565b821015610ba257610b99610b859284610ea6565b90509150610b7b565b50505050565b6305787a5560e41b5f5260045ffd5b908151811015610bc8570160200190565b634e487b7160e01b5f52603260045260245ffd5b60ff60f6199116019060ff821161087c57565b60ff60bf199116019060ff821161087c57565b60ff607f199116019060ff821161087c57565b60ff60b6199116019060ff821161087c57565b805115610d0757610c53610c4d610c3f5f84610bb7565b516001600160f81b03191690565b60f81c90565b9060ff821660bf8111610c69575050505f905f90565b60f710610c8d5750610c7d610c8391610bef565b60ff1690565b906107095f610881565b9190610c7d610c9b91610bdc565b610cad81610ca85f610881565b6108b9565b835110610cff575f925f905b828210610ccf57505061070990610ca85f610881565b909360019060081b610cf6610c7d610c4d610c3f610cf08a610ca85f610881565b87610bb7565b17940190610cb9565b505f91508190565b505f905f90565b9190918051831015610cff57610d2a610c4d610c3f8584610bb7565b9060ff821660bf8111610d425750505090505f905f90565b60f710610d5f5750610d59610c7d61070992610bef565b92610881565b9290610c7d610d6d91610bdc565b90610d7b82610ca883610881565b845110610dc7575f935f905b838210610d9d57505090610ca861070992610881565b909460019060081b610dbe610c7d610c4d610c3f610cf08b610ca88a610881565b17950190610d87565b505090505f905f90565b8051821015610ba857610dea610c4d610c3f8484610bb7565b60ff81169290607f8411610dfe5750505090565b90919392608081145f14610e1457505f93505050565b60818110159081610e9a575b5015610ba857610c7d610e3291610c02565b90610e4082610ca883610881565b845110610ba85792905f935f925b828410610e5b5750505050565b90919294610e7660019167ffffffffffffff009060081b1690565b610e8f610c7d610c4d610c3f610cf08b610ca88a610881565b179501929190610e4e565b6088915011155f610e20565b9190918051831015610ba857610ec2610c4d610c3f8584610bb7565b9060ff8216607f8111610ee15750505090610edc90610881565b600191565b60b78111610f0c575050610efa610c7d61070992610c02565b610ca8610f068261088f565b94610881565b60bf8111610f78575090610c7d610f2291610c15565b5f915f905b828210610f4e57505090610ca882610ca8610f4884610ca86107099761088f565b96610881565b909260019060081b610f6f610c7d610c4d610c3f610cf089610ca88d610881565b17930190610f27565b60f710610f8f5750610efa610c7d61070992610bef565b90610c7d610f9c91610bdc565b5f915f905b828210610fc257505090610ca882610ca8610f4884610ca86107099761088f565b909260019060081b610fe3610c7d610c4d610c3f610cf089610ca88d610881565b17930190610fa1565b602003906020821161087c57565b5f1981019190821161087c57565b600381901b91906001600160fd1b0381160361087c57565b908151811015610ba85761103a610c4d610c3f8385610bb7565b60ff81169060a082036110615750506110528161089d565b825110610ba857016021015190565b909290607f84116110725750505090565b909192608081101590816110e4575b5015610ba857610c7d61109391610c02565b91826110a0575050505f90565b60208311610ba8576110b583610ca883610881565b825110610ba8576110d96110d460216001936110df9501015194610fec565b611008565b1b610ffa565b191690565b60b7915011155f611081565b908151811015610ba85760ff61110c610c4d610c3f8486610bb7565b1660948103611131575061111f816108ab565b825110610ba857016021015160601c90565b608014159150610ba89050575f9056fea2646970667358221220edf4c2545437da93d3b806c70cbb2dec6940eaf8cf99e5dbda66a3e0192368b064736f6c63430008210033","storage":{"0x0000000000000000000000000000000000000000000000000000000000000000":"0xb049644b1d5a0ec9d785dd48f95099e0f566112084acb1ba0814112209b432a1","0x0000000000000000000000000000000000000000000000000000000000000001":"0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002":"0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000003":"0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000004":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","0x0000000000000000000000000000000000000000000000000000000000000005":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","0x0000000000000000000000000000000000000000000000000000000000000006":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","0x0000000000000000000000000000000000000000000000000000000000000007":"0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000008":"0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000009":"0x0000000000000000000000000000000000000000000000000000000000000000"}},"0x1c00000000000000000000000000000000000001":{"nonce":"0x1","balance":"0x0","code":"0x60806040526004361015610011575f80fd5b5f3560e01c80631fbb25ad1461008457806379502c551461007f57806382648c3b1461007a578063a21de6d914610075578063ced9ef9914610070578063d01e8d311461006b5763f3051c0c14610066575f80fd5b6103a1565b6102e1565b61017a565b610136565b61011a565b6100d6565b346100c8575f3660031901126100c8577f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b03166080908152602090f35b5f80fd5b5f9103126100c857565b346100c8575f3660031901126100c8576040517f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03168152602090f35b346100c8575f3660031901126100c85760205f54604051908152f35b346100c8575f3660031901126100c8576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346100c85760203660031901126100c857600435331515806101ed575b6101de576101d9816101c97f56da6c5890b0d58ee4cdad987616c4b1cfef3d3c4b1e4827682219e8065d01a893600155565b6040519081529081906020820190565b0390a1005b63bb62587160e01b5f5260045ffd5b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa90811561027c575f9161024d575b506001600160a01b0316331415610197565b61026f915060203d602011610275575b61026781836103f2565b810190610424565b5f61023b565b503d61025d565b61043c565b9181601f840112156100c8578235916001600160401b0383116100c8576020808501948460051b0101116100c857565b9181601f840112156100c8578235916001600160401b0383116100c85760208085019460c085020101116100c857565b346100c85760803660031901126100c8576004356001600160401b0381116100c857366023820112156100c8578060040135906001600160401b0382116100c85736602483830101116100c8576024356001600160401b0381116100c85761034d903690600401610281565b6044929192356001600160401b0381116100c85761036f9036906004016102b1565b91606435946001600160401b0386116100c85761039f966103966024973690600401610281565b97909601610a57565b005b346100c8575f3660031901126100c8576020600154604051908152f35b634e487b7160e01b5f52604160045260245ffd5b60a081019081106001600160401b038211176103ed57604052565b6103be565b90601f801991011681019081106001600160401b038211176103ed57604052565b6001600160a01b038116036100c857565b908160209103126100c8575161043981610413565b90565b6040513d5f823e3d90fd5b908060209392818452848401375f828201840152601f01601f1916010190565b916020610439938181520191610447565b634e487b7160e01b5f52603260045260245ffd5b91908110156104ae5760051b81013590607e19813603018212156100c8570190565b610478565b3561043981610413565b903590601e19813603018212156100c857018035906001600160401b0382116100c8576020019181360383136100c857565b95939161051b906105299461043999979360018060a01b03168952608060208a01526080890191610447565b918683036040880152610447565b926060818503910152610447565b91908110156104ae5760051b81013590603e19813603018212156100c8570190565b6002111561056357565b634e487b7160e01b5f52602160045260245ffd5b3560028110156100c85790565b35906001600160801b03821682036100c857565b60ff8116036100c857565b6001600160401b0381116103ed57601f01601f191660200190565b35906001600160a01b0319821682036100c857565b35906001600160801b0319821682036100c857565b6020818303126100c8578035906001600160401b0382116100c857019060a0828203126100c8576040519161061c836103d2565b803561062781610413565b8352602081013561063781610413565b602084015261064860408201610584565b6040840152606081013560608401526080810135906001600160401b0382116100c857019060a0828203126100c85760405191610684836103d2565b80358352602081013561069681610598565b602084015260408101356001600160401b0381116100c85781019082601f830112156100c8578135926106c8846105a3565b906106d660405192836103f2565b848252602085850101116100c8575f6020856107159682608097018386013783010152604085015261070a606082016105be565b6060850152016105d3565b6080820152608082015290565b634e487b7160e01b5f52601160045260245ffd5b5f1981146107445760010190565b610722565b91908110156104ae5760c0020190565b3561043981610598565b519081151582036100c857565b908160209103126100c85761043990610763565b604051906107936040836103f2565b600d82526c65636965732d6165732d6b657960981b6020830152565b91906040838203126100c85782516001600160401b0381116100c857830181601f820112156100c8578051916107e4836105a3565b906107f260405192836103f2565b838252602084840101116100c8575f60208461043995828096018386015e830101529301610763565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b926108759060809360209397969786526bffffffffffffffffffffffff60a01b168386015260a0604086015260a085019061081b565b83810360608501525f815201936001600160801b031916910152565b9060028210156105635752565b92919060806040916108b1866001610891565b6060602087015260018060a01b03815116606087015260018060a01b03602082015116828701526001600160801b03838201511660a0870152606081015160c0870152015160a060e0860152805161010086015260ff60208201511661012086015261092d8282015160a06101408801526101a087019061081b565b60608201516001600160a01b0319166101608701526080909101516001600160801b031916610180860152930152565b908160a09103126100c857608060405191610977836103d2565b803561098281610413565b8352602081013561099281610413565b602084015260408101356109a581610413565b60408401526109b660608201610584565b60608401520135608082015290565b60c09093929193608060e08201956109dd835f610891565b80516001600160a01b039081166020858101919091528201518116604080860191909152820151166060808501919091528101516001600160801b031682840152015160a08201520152565b908160209103126100c8575190565b908160209103126100c857516001600160401b03811681036100c85790565b9591949392969033151580611481575b6101de576001548015159081611477575b50611468577f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b031696873b156100c85760405163fe77009960e01b8152915f9183918291610ad1919060048401610467565b0381838b5af1801561027c57611454575b505f9492945b8181106113a8575050505f54925f915f915b878310610c915750505003610c82576040516381e3da6b60e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166004808301919091526024820152602081604481865afa801561027c57610c65575b505f819055604051631014997960e31b815291602083600481845afa92831561027c575f93610c30575b50602060049160405192838092631d04645f60e01b82525afa801561027c577f87977a3515c59199065d0e2d7837b95d8fcf5fb072c0321138df0786011e32c4926001600160401b03925f92610bfb575b5060408051968752602087019190915291169390819081015b0390a3565b610bf6919250610c229060203d602011610c29575b610c1a81836103f2565b810190610a38565b9190610bdd565b503d610c10565b6004919350610c56602091823d8411610c5e575b610c4e81836103f2565b810190610a29565b939150610b8c565b503d610c44565b610c7d9060203d602011610c5e57610c4e81836103f2565b610b62565b6361aba18160e11b5f5260045ffd5b909194610c9f868985610537565b610ca881610577565b610cb181610559565b610e6657610cc6816020610cce9301906104bd565b81019061095d565b90604051610cf381610ce5602082019486866109c5565b03601f1981018352826103f2565b5190208151909690610d1b90610d0f906001600160a01b031681565b6001600160a01b031690565b6040830180519091906001600160a01b0316906060850191610d4483516001600160801b031690565b823b156100c8576040516340c10f1960e01b81526001600160a01b039290921660048301526001600160801b03166024820152905f908290604490829084905af1801561027c576001958b927fd5277bc9597c7da3fab9cdbba4de6005f48b9eb7389cf2389c4ea9eea3172c2192610e4c575b506020810151610dd8906001600160a01b031695516001600160a01b031690565b8151610e4090608090610dfd906001600160a01b03165b97516001600160801b031690565b930151604080516001600160a01b0390981688526001600160801b0390941660208801529286019290925260a088901b8890039081169516939081906060820190565b0390a45b019190610afa565b80610e5a5f610e60936103f2565b806100cc565b5f610db7565b610e7a816020610e829399949901906104bd565b8101906105e8565b908585101561139957610e9f610e9786610736565b958785610749565b60608301610ead8151611531565b9160808601926020608086610f338751610ecc85825192015160ff1690565b95833598610edb878601610759565b604051635f8a996960e01b8152600481019490945260ff9889166024850152604484018b905288166064840152608483015290951660a48601529101803560c48501526020013560e484015282908190610104820190565b0381731c000000000000000000000000000000000001005afa90811561027c575f9161136b575b501561135c57518251516040516bffffffffffffffffffffffff197f000000000000000000000000000000000000000000000000000000000000000060601b166020820152603481019290925260548083019190915281525f91610fd29190610fc46074836103f2565b610fcc610784565b906116a2565b915160608101519092906001600160a01b0319169061101f611004608060408701519601516001600160801b03191690565b60405163f4a7eb1360e01b815295869485946004860161083f565b0381731c000000000000000000000000000000000001015afa801561027c575f915f91611338575b508061132d575b156113255761105c9061170e565b9061106c610d0f604085016104b3565b6001600160a01b03909116149081611317575b50975b60405161109881610ce56020820194888661089e565b519020976111d2575081516110b790610d0f906001600160a01b031681565b602083018051909391906001600160a01b03169160408101926110e184516001600160801b031690565b833b156100c8576040516340c10f1960e01b81526001600160a01b039290921660048301526001600160801b03166024820152915f908390604490829084905af190811561027c5761118861117a61116c6001988e967f95705d99ac13cf82894fd274cd871942e6f301c98c186271337e8fedbbb9d7ea966111be575b50516001600160a01b031690565b92516001600160a01b031690565b94516001600160801b031690565b604080516001600160a01b039690961686526001600160801b0391909116602086015260a087901b8790039190911693a3610e44565b80610e5a5f6111cc936103f2565b5f61115e565b82516111e890610d0f906001600160a01b031681565b9060408101916111f7836104b3565b91604086019261120e84516001600160801b031690565b833b156100c8576040516340c10f1960e01b81526001600160a01b039290921660048301526001600160801b03166024820152915f908390604490829084905af190811561027c576001968c937ffc236d1b4402e76c2b0a882db36ad3a6fb0f5b6b7edc8ae317d993f10434c43693611303575b506112fb60606112b8610def6112aa6112a4602087015160018060a01b031690565b9a6104b3565b94516001600160a01b031690565b604080516001600160a01b0390991689526001600160801b0390911660208901529301359286019290925260a088901b8890039081169516939081906060820190565b0390a4610e44565b80610e5a5f611311936103f2565b5f611282565b90506060820135145f61107f565b505f97611082565b50604081511461104e565b905061135691503d805f833e61134e81836103f2565b8101906107af565b5f611047565b63fb1f4a4960e01b5f5260045ffd5b61138c915060203d8111611392575b61138481836103f2565b810190610770565b5f610f5a565b503d61137a565b6351de8c1f60e01b5f5260045ffd5b6113b681838598969861048c565b906113ee6113c3836104b3565b926113d160208201826104bd565b9490916113e160408201826104bd565b94909160608101906104bd565b9061083f60921b3b156100c8575f9561141c93604051998a9788976374ae5b3760e11b8952600489016104ef565b03818361083f60921b5af191821561027c57600192611440575b5001949294610ae8565b80610e5a5f61144e936103f2565b5f611436565b80610e5a5f611462936103f2565b5f610ae2565b632f31b33b60e01b5f5260045ffd5b905088115f610a78565b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa90811561027c575f916114e1575b506001600160a01b0316331415610a67565b6114fa915060203d6020116102755761026781836103f2565b5f6114cf565b908160011b918083046002149015171561074457565b906001820180921161074457565b9190820180921161074457565b6115629061155c604051602081019061155381610ce584906006602083019252565b51902091611500565b90611524565b906115eb61156f83611516565b6040516381e3da6b60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000818116600484015260248301969096527f0000000000000000000000001c0000000000000000000000000000000000000016949092909190602090849081906044820190565b0381885afa92831561027c575f9361166f575b50821561135c576040516381e3da6b60e01b81526001600160a01b03929092166004830152602482015292602090849060449082905afa92831561027c575f9361164b575b509160ff1690565b60ff9193506116689060203d602011610c5e57610c4e81836103f2565b9290611643565b61168991935060203d602011610c5e57610c4e81836103f2565b915f6115fe565b805191908290602001825e015f815290565b916116f660016116d0610439956116e195604051916020830152602082526116cb6040836103f2565b611757565b926040519485916020830190611690565b8260f81b815203601e198101855201836103f2565b604051906020820152602081526116cb6040826103f2565b9081516040810361172a57506034602083015160601c92015190565b633fbbeba160e21b5f52600452604060245260445ffd5b6104399392604092825260208201520190611690565b5f908051604081115f1461186357505f61177960209260405191828092611690565b039060025afa1561027c5760205f6117f4610ce56117e88351965b6040519283917f363636363636363636363636363636363636363636363636363636363636363689187f36363636363636363636363636363636363636363636363636363636363636368b18898501611741565b60405191828092611690565b039060025afa1561027c576118537f5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c6117e85f93610ce56020968651908560405196879518911889850191606093918352602083015260408201520190565b039060025afa1561027c575f5190565b60208083015194908211935091600184146118d257505f925b602082106118bc575b60408210166118a2575b505f6117f4610ce56117e8602094611794565b600160409190910360031b1b5f190119909116905f61188f565b935f1960018360200360031b1b01191693611885565b604001519261187c56fea26469706673582212208d8a42523ffb186688985d2f73794a8e068b9808cc21763bbbe8f12397b181cd64736f6c63430008210033"},"0x1c00000000000000000000000000000000000002":{"nonce":"0x1","balance":"0x0","code":"0x6080806040526004361015610012575f80fd5b5f3560e01c9081632c37826e14610776575080633406527214610751578063378fa8fa1461073657806343c3cb831461071b57806344ee09321461069157806348aa41081461063757806353a8d7391461061b578063545525f1146105fe57806379502c55146105ba57806379fa3289146104ae5780637b9c9aa41461046e578063a94cd931146103eb578063b3b200aa14610347578063b79a6c0c1461024c578063bba9282e14610224578063c9b6ca9b14610208578063ce7025e914610135578063d93af1d2146101135763f490ca96146100ed575f80fd5b3461010f575f36600319011261010f576020604051670de0b6b3a76400008152f35b5f80fd5b3461010f575f36600319011261010f57602061012d610990565b604051908152f35b3461010f57606036600319011261010f5761014e610792565b604435906001600160401b03821161010f573660238301121561010f578160040135916001600160401b03831161010f5760248360051b82010136811161010f57610198846108d0565b936101a660405195866108af565b84526024820191602085015b8284106101c857602061012d8787600435610b47565b83356001600160401b03811161010f5782013660438201121561010f576020916101fd8392369060446024820135910161094b565b8152019301926101b2565b3461010f575f36600319011261010f57602060405161c3508152f35b3461010f575f36600319011261010f5760206001600160401b035f5460801c16604051908152f35b3461010f57602036600319011261010f57600435331515806102ad575b61029e576020817f4f0c4dec68e1e774843a5fc3a522ab2a832ecfc975b9ad8a5033736d9e47f09d92600555604051908152a1005b63bb62587160e01b5f5260045ffd5b50604051630b83774760e31b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa90811561033c575f9161030d575b506001600160a01b0316331415610269565b61032f915060203d602011610335575b61032781836108af565b8101906108e7565b826102fb565b503d61031d565b6040513d5f823e3d90fd5b3461010f5761010036600319011261010f576103616107d4565b6103696107ea565b6103716107be565b6103796107a8565b610381610800565b9060c4356001600160401b03811161010f576103a1903690600401610816565b95909360e4356001600160401b03811161010f576103e9976103d76103cd6103df933690600401610816565b989092369161094b565b96369161094b565b95606435926111e6565b005b3461010f5760e036600319011261010f576104046107d4565b61040c6107ea565b6104146107be565b61041c6107a8565b610424610800565b9060c435946001600160401b03861161010f5761045261044b6103e9973690600401610816565b369161094b565b93604051956104626020886108af565b5f8752606435926111e6565b3461010f57602036600319011261010f576004356001600160401b038116810361010f5761049d602091610906565b6001600160801b0360405191168152f35b3461010f57602036600319011261010f576004356001600160801b03811680910361010f573315158061053b575b61029e57670de0b6b3a7640000811161052c576020817f6f864cce5237e12ffc9a99fc6c59af17222c2bbb3457690cc8753ab16b5d715e926001600160801b03195f5416175f55604051908152a1005b630d62f21160e11b5f5260045ffd5b50604051630b83774760e31b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa90811561033c575f9161059b575b506001600160a01b03163314156104dc565b6105b4915060203d6020116103355761032781836108af565b82610589565b3461010f575f36600319011261010f576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461010f575f36600319011261010f576020600554604051908152f35b3461010f575f36600319011261010f5760206040516104008152f35b3461010f575f36600319011261010f575f602060405161065681610864565b82815201526040805161066881610864565b6001600160401b0360015491828152602082600254169101908152835192835251166020820152f35b3461010f57604036600319011261010f5760206004356106af610792565b816106bf60035460045490610843565b809111610713575b506106d1826108d0565b906106df60405192836108af565b828252601f196106ee846108d0565b01925f5b848110610704575061012d9350610b47565b606084820187015285016106f2565b9150836106c7565b3461010f575f36600319011261010f57602060405160718152f35b3461010f575f36600319011261010f57602060405160218152f35b3461010f575f36600319011261010f5760206001600160801b035f5416604051908152f35b3461010f575f36600319011261010f576020905f5460c01c8152f35b602435906001600160401b038216820361010f57565b608435906001600160401b038216820361010f57565b604435906001600160801b038216820361010f57565b600435906001600160a01b038216820361010f57565b602435906001600160a01b038216820361010f57565b60a435906001600160a01b038216820361010f57565b9181601f8401121561010f578235916001600160401b03831161010f576020838186019501011161010f57565b9190820391821161085057565b634e487b7160e01b5f52601160045260245ffd5b604081019081106001600160401b0382111761087f57604052565b634e487b7160e01b5f52604160045260245ffd5b61016081019081106001600160401b0382111761087f57604052565b90601f801991011681019081106001600160401b0382111761087f57604052565b6001600160401b03811161087f5760051b60200190565b9081602091031261010f57516001600160a01b038116810361010f5790565b6001600160401b031661c350016001600160401b038111610850576001600160401b036001600160801b035f54169116026001600160801b0381169081036108505790565b9291926001600160401b03821161087f5760405191610974601f8201601f1916602001846108af565b82948184528183011161010f578281602093845f960137010152565b60045460035490818110156109ab576109a891610843565b90565b50505f90565b6003548110156109cd5760035f52600960205f20910201905f90565b634e487b7160e01b5f52603260045260245ffd5b90600182811c92168015610a0f575b60208310146109fb57565b634e487b7160e01b5f52602260045260245ffd5b91607f16916109f0565b9060405191825f825492610a2c846109e1565b8084529360018116908115610a975750600114610a53575b50610a51925003836108af565b565b90505f9291925260205f20905f915b818310610a7b575050906020610a51928201015f610a44565b6020919350806001915483858901015201910190918492610a62565b905060209250610a5194915060ff191682840152151560051b8201015f610a44565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b5f5b828110610aeb57505050565b5f82820155600101610adf565b610b0281546109e1565b9081610b0c575050565b81601f5f9311600114610b1d575055565b81835260208320610b3a91601f0160051c84190190600101610add565b8082528160208120915555565b9092915f9333151580611167575b61029e576001600160401b0380431691160361115857600354610b7b6004548092610843565b808411611150575b508151838103611139575082610c2a575b5050505f5460018160c01c01906001600160401b038211610850576001600160c01b031660c091821b6001600160c01b031916175f81905560405184927fec4aff46c65f485f4b15e3c2edadda1d57d002995f5aa262a27c76b9a680ec1692602092911c9081908390610c0681610864565b868152015283600155806001600160401b03196002541617600255604051908152a2565b5f1994509182019190828211610850579082915b818311610df65750505080600455600354809114610c5e575b8080610b94565b5f60035580610c73575b505f6004555f610c57565b806009029060098204036108505760035f525f5b818110610c945750610c68565b6009905f817fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b01555f7fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c8201555f7fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85d8201555f7fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85e8201555f7fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85f8201555f7fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f8608201555f7fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f861820155610dc57fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f8628201610af8565b610df07fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f8638201610af8565b01610c87565b9091945f19860195861161085057610e0d866109b1565b5060405190610e1b82610893565b60018060a01b03815416825260018060a01b036001820154169260208301938452886002830154936040810194855260018060a01b0360038501541693606082019485526004810154918960808201976001600160801b038516895260a083019460801c855260058401549060c08401918252600685015493610eea60e08201946001600160401b038716865261010083019660018060a01b039060401c168752610edc6008610ecd60078b01610a19565b9961012086019a8b5201610a19565b9961014084019a8b52610843565b8d518110156109cd5760051b8d0160200151975151611132575f5b885181810361111d5750506001600160801b036001600160401b0392819260018060a01b039051169d5190516040519060208201926bffffffffffffffffffffffff199060601b168352603482015260348152610f636054826108af565b5190209a60018060a01b039051169b511696511691519251169260018060a01b039051169351946040519a6101408c018c81106001600160401b0382111761087f576040528b5260208b0198895260408b01998a5260608b0190815260808b0191825260a08b0192835260c08b0193845260e08b019485526101008b019586526101208b01968752604051998a9960208b019c60408e52600160a01b6001900390511660608c01525160808b0152600160a01b6001900390511660a08a0152516001600160801b031660c0890152516001600160801b031660e088015251610100870152516001600160401b0316610120860152600160a01b6001900390511661014085015251610160840161014090526101a0840161108291610ab9565b9051838203605f190161018085015261109b9190610ab9565b90604083015203601f19810182526110b390826108af565b519020946110c0816109b1565b61110a576008815f61110393555f60018201555f60028201555f60038201555f60048201555f60058201555f60068201556110fd60078201610af8565b01610af8565b9190610c3e565b634e487b7160e01b5f525f60045260245ffd5b63521a2d4d60e11b5f5260045260245260445ffd5b6071610f05565b8390630db2128560e11b5f5260045260245260445ffd5b92505f610b83565b631391e11b60e21b5f5260045ffd5b50604051630b83774760e31b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa90811561033c575f916111c7575b506001600160a01b0316331415610b55565b6111e0915060203d6020116103355761032781836108af565b5f6111b5565b5f969195909491936001600160a01b0390911692831561189c5761040085511161188d57611213896118ab565b60055480611848575b506001600160801b038061122f85610906565b92169116908181016001600160801b0381116108505760405163868a2e9d60e01b8152946020866004815f60056007609a1b015af195861561033c575f96611814575b508515611805576040516323b872dd60e01b81523360048201523060248201526001600160801b0392909216604483018190526001600160a01b0390991698916020816064815f8e5af190811561033c575f916117ca575b50156117bb57883b1561010f5760405191630852cd8d60e31b835260048301525f82602481838d5af191821561033c578c926117a4575b50876040519161131083610893565b8a8352886020840198338a5260408501908152606085019d60018060a01b03169d8e8152608086019088825260a08701908a825260c08801938c85526001600160401b0360e08a0197169d8e88526101008a019687526101208a019889526101408a019a8b526003546801000000000000000081101561178a5780600161139a92016003556109b1565b9a909a61177157518a546001600160a01b03199081166001600160a01b03928316178c55915160018c0180548416918316919091179055915160028b0155915160038a01805490931691161790559051905160801b6fffffffffffffffffffffffffffffffff19166001600160801b0391909116176004860155516005850155905160068401805492516001600160e01b03199093166001600160401b039283161760409390931b68010000000000000000600160e01b031692909217909155905180516007840192909190821161175d578d9061147884546109e1565b601f811161171a575b50602091601f84116001146116b45760089594936114b5939092836115e7575b50508160011b915f199060031b1c19161790565b90555b01905180516001600160401b0381116116a0578b6114d684546109e1565b601f8111611654575b505060208c601f83116001146115f2579061150d93836115e75750508160011b915f199060031b1c19161790565b90555b8854986001600160401b038a60801c16996001600160401b038b146115d357926115be95927f348c28d1410ff29393c038fe0f1998384082e98e315624b24c04a4fa6288b9de9a999895926115ce98958d60016001600160401b0360801b910160801b16906001600160401b0360801b1916179055604051998a998a5260208a015260408901526060880152608087015260a086015260c085015261012060e0850152610120840190610ab9565b8281036101008401523396610ab9565b0390a3565b634e487b7160e01b82526011600452602482fd5b015190505f806114a1565b9192601f198416858452828420935b81811061163c5750908460019594939210611624575b505050811b019055611510565b01515f1960f88460031b161c191690555f8080611617565b92936020600181928786015181550195019301611601565b84838211611663575b506114df565b61169092528d6020812091601f850160051c9160208610611698575b50601f82910160051c039101610add565b8b5f8461165d565b91508f61167f565b634e487b7160e01b8c52604160045260248cfd5b9190601f198416858452828420935b8181106117025750916001939185600898979694106116ea575b505050811b0190556114b8565b01515f1960f88460031b161c191690555f80806116dd565b929360206001819287860151815501950193016116c3565b838111156114815761174f908584526020842090601f860160051c9060208710611755575b601f82910160051c039101610add565b5f611481565b85915061173f565b634e487b7160e01b8e52604160045260248efd5b50505050505060248f634e487b7160e01b815280600452fd5b50505050505060248f634e487b7160e01b81526041600452fd5b5f919b506117b292506108af565b895f995f611301565b6312171d8360e31b5f5260045ffd5b90506020813d6020116117fd575b816117e5602093836108af565b8101031261010f5751801515810361010f575f6112ca565b3d91506117d8565b632968ee7f60e21b5f5260045ffd5b9095506020813d602011611840575b81611830602093836108af565b8101031261010f5751945f611272565b3d9150611823565b6007544303611880575b60065490811015611871575f198114610850576001016006555f61121c565b63124ab48560e11b5f5260045ffd5b436007555f600655611852565b634b8a874d60e11b5f5260045ffd5b63c29f0c7160e01b5f5260045ffd5b80518015611903576021036118e5578051156109cd57602001516001600160f81b031916600160f91b81141590816118f4575b506118e557565b6361d0136b60e11b5f5260045ffd5b600360f81b141590505f6118de565b505056fea2646970667358221220652e7449c8658b6fc3b3333b742e8b3959d13566217fc352249d4a8ad22860c164736f6c63430008220033"},"0x1c00000000000000000000000000000000000003":{"nonce":"0x1","balance":"0x0","code":"0x6080806040526004361015610012575f80fd5b5f3560e01c9081631beb1ab814610561575080631fbb25ad1461051d5780633488ce0d146102dd5780635c1bba381461023b5780636d46e98714610193578063a21de6d91461014f5763e202d99514610069575f80fd5b34610138575f366003190112610138576040516381e3da6b60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260016024830152602090829060449082907f0000000000000000000000001c00000000000000000000000000000000000000165afa8015610144575f9061010d575b6040516001600160a01b039091168152602090f35b506020813d60201161013c575b816101276020938361067c565b8101031261013857602090516100f8565b5f80fd5b3d915061011a565b6040513d5f823e3d90fd5b34610138575f366003190112610138576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610138576020366003190112610138576004356001600160a01b0381169081900361013857604051630b83774760e31b8152602081600481305afa908115610144575f916101f6575b506040516001600160a01b039091169091148152602090f35b90506020813d602011610233575b816102116020938361067c565b810103126101385751906001600160a01b0382168203610138579060206101dd565b3d9150610204565b34610138575f366003190112610138576040516381e3da6b60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301525f6024830152602090829060449082907f0000000000000000000000001c00000000000000000000000000000000000000165afa8015610144575f9061010d576040516001600160a01b039091168152602090f35b34610138575f366003190112610138576040516381e3da6b60e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b038181166004840152600660248401527f0000000000000000000000001c00000000000000000000000000000000000000169190602082604481865afa918215610144575f926104e9575b5081156104da576040516020810190600682526020815261038f60408261067c565b519020915f1981019081116104c6578060011b90808204600214901517156104c65782018092116104c65760018201908183116104c6576040516381e3da6b60e01b81526001600160a01b03821660048201526024810193909352602083604481875afa928315610144575f9361048e575b506040516381e3da6b60e01b81526001600160a01b03909116600482015260248101919091529160209083908180604481015b03915afa918215610144575f92610459575b5060ff6040928351928352166020820152f35b91506020823d602011610486575b816104746020938361067c565b810103126101385790519060ff610446565b3d9150610467565b919092506020823d6020116104be575b816104ab6020938361067c565b8101031261013857905191610434610401565b3d915061049e565b634e487b7160e01b5f52601160045260245ffd5b630c322fb560e31b5f5260045ffd5b9091506020813d602011610515575b816105056020938361067c565b810103126101385751908361036d565b3d91506104f8565b34610138575f366003190112610138576040517f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b03168152602090f35b34610138576020366003190112610138576004356001600160a01b0381169190829003610138576105fe9181602080930191825260076040820152604081526105ab60608261067c565b5190206040516381e3da6b60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166004820152602481019190915291829081906044820190565b03817f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b03165afa8015610144575f90610649575b60209060ff604051911615158152f35b506020813d602011610674575b816106636020938361067c565b810103126101385760209051610639565b3d9150610656565b90601f8019910116810190811067ffffffffffffffff82111761069e57604052565b634e487b7160e01b5f52604160045260245ffdfea2646970667358221220615455022182404b5eef598e1c4e66b9fba2ee08aa579832c0c247d1afef17a164736f6c63430008210033"},"0x1c00000000000000000000000000000000000004":{"nonce":"0x1","balance":"0x0","code":"0xfe"},"0x20c0000000000000000000000000000000000000":{"nonce":"0x0","balance":"0x0","code":"0xef","storage":{"0x0000000000000000000000000000000000000000000000000000000000000002":"0x706174685553440000000000000000000000000000000000000000000000000e","0x0000000000000000000000000000000000000000000000000000000000000003":"0x706174685553440000000000000000000000000000000000000000000000000e","0x0000000000000000000000000000000000000000000000000000000000000004":"0x5553440000000000000000000000000000000000000000000000000000000006","0x0000000000000000000000000000000000000000000000000000000000000006":"0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000007":"0x0000000000000000000000010000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000008":"0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000000000000000000000000000000000000d":"0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff","0x1a08d1eefb6dea6eba7c6c1f53fa17f31dc24b9efe98e97550f0dad434642618":"0x0000000000000000000000000000000000000000000000000000000000000001","0x353fe882519f79b8caf8d301c26c19d663ae2e691ca2e75dc341b346d5d22c63":"0x0000000000000000000000000000000000000000000000000000000000000001","0x983ee3ed0ac6ffe1e6626c807d5dad57db7645721c041f19b39c3f728acefdd7":"0x0000000000000000000000000000000000000000000000000000000000000001","0x9a3d8dc9bf2bb7465d975ea80af65f820bc69e3b43668ac11765d4e28cf9333a":"0x0000000000000000000000000000000000000000000000000000000000000001","0xad6e221fb67208b50def8b13e82392da7f9eaacd7b17f77c8bfdc7df401bc3d8":"0x0000000000000000000000000000000000000000000000000000000000000000","0xbd1422d956203483f6a77a55f068041e264cef0ec8c355db258a1fb8f4169a51":"0x0000000000000000000000000000000000000000000000000000000000000001","0xc39d774f18115b85b81494d65e588b565d73abc969333d1da7b0a0eb0729accd":"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}},"0x20c0000000000000000000000000000000000001":{"nonce":"0x0","balance":"0x0","code":"0xef","storage":{"0x0000000000000000000000000000000000000000000000000000000000000002":"0x416c706861555344000000000000000000000000000000000000000000000010","0x0000000000000000000000000000000000000000000000000000000000000003":"0x416c706861555344000000000000000000000000000000000000000000000010","0x0000000000000000000000000000000000000000000000000000000000000004":"0x5553440000000000000000000000000000000000000000000000000000000006","0x0000000000000000000000000000000000000000000000000000000000000006":"0x00000000000000000000000020c0000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000007":"0x00000000000000000000000120c0000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000008":"0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000000000000000000000000000000000000d":"0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff","0x1a08d1eefb6dea6eba7c6c1f53fa17f31dc24b9efe98e97550f0dad434642618":"0x0000000000000000000000000000000000000000000000000000000000000001","0x353fe882519f79b8caf8d301c26c19d663ae2e691ca2e75dc341b346d5d22c63":"0x0000000000000000000000000000000000000000000000000000000000000001","0x983ee3ed0ac6ffe1e6626c807d5dad57db7645721c041f19b39c3f728acefdd7":"0x0000000000000000000000000000000000000000000000000000000000000001","0x9a3d8dc9bf2bb7465d975ea80af65f820bc69e3b43668ac11765d4e28cf9333a":"0x0000000000000000000000000000000000000000000000000000000000000001","0xbd1422d956203483f6a77a55f068041e264cef0ec8c355db258a1fb8f4169a51":"0x0000000000000000000000000000000000000000000000000000000000000001","0xc39d774f18115b85b81494d65e588b565d73abc969333d1da7b0a0eb0729accd":"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}},"0x20c0000000000000000000000000000000000002":{"nonce":"0x0","balance":"0x0","code":"0xef","storage":{"0x0000000000000000000000000000000000000000000000000000000000000002":"0x426574615553440000000000000000000000000000000000000000000000000e","0x0000000000000000000000000000000000000000000000000000000000000003":"0x426574615553440000000000000000000000000000000000000000000000000e","0x0000000000000000000000000000000000000000000000000000000000000004":"0x5553440000000000000000000000000000000000000000000000000000000006","0x0000000000000000000000000000000000000000000000000000000000000006":"0x00000000000000000000000020c0000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000007":"0x00000000000000000000000120c0000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000008":"0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000000000000000000000000000000000000d":"0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff","0x1a08d1eefb6dea6eba7c6c1f53fa17f31dc24b9efe98e97550f0dad434642618":"0x0000000000000000000000000000000000000000000000000000000000000001","0x353fe882519f79b8caf8d301c26c19d663ae2e691ca2e75dc341b346d5d22c63":"0x0000000000000000000000000000000000000000000000000000000000000001","0x983ee3ed0ac6ffe1e6626c807d5dad57db7645721c041f19b39c3f728acefdd7":"0x0000000000000000000000000000000000000000000000000000000000000001","0x9a3d8dc9bf2bb7465d975ea80af65f820bc69e3b43668ac11765d4e28cf9333a":"0x0000000000000000000000000000000000000000000000000000000000000001","0xbd1422d956203483f6a77a55f068041e264cef0ec8c355db258a1fb8f4169a51":"0x0000000000000000000000000000000000000000000000000000000000000001","0xc39d774f18115b85b81494d65e588b565d73abc969333d1da7b0a0eb0729accd":"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}},"0x20fc000000000000000000000000000000000000":{"nonce":"0x0","balance":"0x0","code":"0xef"},"0x403c000000000000000000000000000000000000":{"nonce":"0x0","balance":"0x0","code":"0xef"},"0x4e4f4e4345000000000000000000000000000000":{"nonce":"0x0","balance":"0x0","code":"0xef"},"0x4e59b44847b379578588920ca78fbf26c0b4956c":{"nonce":"0x1","balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3"},"0x914d7fec6aac8cd542e72bca78b30650d45643d7":{"nonce":"0x1","balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3"},"0xaaaaaaaa00000000000000000000000000000000":{"nonce":"0x0","balance":"0x0","code":"0xef"},"0xba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed":{"nonce":"0x1","balance":"0x0","code":"0x60806040526004361061018a5760003560e01c806381503da1116100d6578063d323826a1161007f578063e96deee411610059578063e96deee414610395578063f5745aba146103a8578063f9664498146103bb57600080fd5b8063d323826a1461034f578063ddda0acb1461036f578063e437252a1461038257600080fd5b80639c36a286116100b05780639c36a28614610316578063a7db93f214610329578063c3fe107b1461033c57600080fd5b806381503da1146102d0578063890c283b146102e357806398e810771461030357600080fd5b80632f990e3f116101385780636cec2536116101125780636cec25361461027d57806374637a7a1461029d5780637f565360146102bd57600080fd5b80632f990e3f1461023757806331a7c8c81461024a57806342d654fc1461025d57600080fd5b806327fe18221161016957806327fe1822146101f15780632852527a1461020457806328ddd0461461021757600080fd5b8062d84acb1461018f57806326307668146101cb57806326a32fc7146101de575b600080fd5b6101a261019d366004612915565b6103ce565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6101a26101d9366004612994565b6103e6565b6101a26101ec3660046129db565b610452565b6101a26101ff3660046129db565b6104de565b6101a2610212366004612a39565b610539565b34801561022357600080fd5b506101a2610232366004612a90565b6106fe565b6101a2610245366004612aa9565b61072a565b6101a2610258366004612aa9565b6107bb565b34801561026957600080fd5b506101a2610278366004612b1e565b6107c9565b34801561028957600080fd5b506101a2610298366004612a90565b610823565b3480156102a957600080fd5b506101a26102b8366004612b4a565b61084f565b6101a26102cb3660046129db565b611162565b6101a26102de366004612b74565b6111e8565b3480156102ef57600080fd5b506101a26102fe366004612bac565b611276565b6101a2610311366004612bce565b6112a3565b6101a2610324366004612994565b611505565b6101a2610337366004612c49565b6116f1565b6101a261034a366004612aa9565b611964565b34801561035b57600080fd5b506101a261036a366004612cd9565b6119ed565b6101a261037d366004612c49565b611a17565b6101a2610390366004612bce565b611e0c565b6101a26103a3366004612915565b611e95565b6101a26103b6366004612bce565b611ea4565b6101a26103c9366004612b74565b611f2d565b60006103dd8585858533611a17565b95945050505050565b6000806103f2846120db565b90508083516020850134f59150610408826123d3565b604051819073ffffffffffffffffffffffffffffffffffffffff8416907fb8fda7e00c6b06a2b54e58521bc5894fee35f1090e5a3bb6390bfe2b98b497f790600090a35092915050565b60006104d86104d260408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b836103e6565b92915050565b600081516020830134f090506104f3816123d3565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f4db17dd5e4732fb6da34a148104a592783ca119a1e7bb8829eba6cbadef0b51190600090a2919050565b600080610545856120db565b905060008460601b90506040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528160148201527f5af43d82803e903d91602b57fd5bf300000000000000000000000000000000006028820152826037826000f593505073ffffffffffffffffffffffffffffffffffffffff8316610635576040517fc05cee7a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed1660048201526024015b60405180910390fd5b604051829073ffffffffffffffffffffffffffffffffffffffff8516907fb8fda7e00c6b06a2b54e58521bc5894fee35f1090e5a3bb6390bfe2b98b497f790600090a36000808473ffffffffffffffffffffffffffffffffffffffff1634876040516106a19190612d29565b60006040518083038185875af1925050503d80600081146106de576040519150601f19603f3d011682016040523d82523d6000602084013e6106e3565b606091505b50915091506106f382828961247d565b505050509392505050565b60006104d87f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed8361084f565b60006107b36107aa60408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b85858533611a17565b949350505050565b60006107b3848484336112a3565b60006040518260005260ff600b53836020527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f6040526055600b20601452806040525061d694600052600160345350506017601e20919050565b60006104d8827f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed6107c9565b600060607f9400000000000000000000000000000000000000000000000000000000000000610887600167ffffffffffffffff612d45565b67ffffffffffffffff16841115610902576040517f3c55ab3b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b836000036109c7576040517fd60000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f800000000000000000000000000000000000000000000000000000000000000060368201526037015b6040516020818303038152906040529150611152565b607f8411610a60576040517fd60000000000000000000000000000000000000000000000000000000000000060208201527fff0000000000000000000000000000000000000000000000000000000000000080831660218301527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b16602283015260f886901b1660368201526037016109b1565b60ff8411610b1f576040517fd70000000000000000000000000000000000000000000000000000000000000060208201527fff0000000000000000000000000000000000000000000000000000000000000080831660218301527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660228301527f8100000000000000000000000000000000000000000000000000000000000000603683015260f886901b1660378201526038016109b1565b61ffff8411610bff576040517fd80000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f820000000000000000000000000000000000000000000000000000000000000060368201527fffff00000000000000000000000000000000000000000000000000000000000060f086901b1660378201526039016109b1565b62ffffff8411610ce0576040517fd90000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f830000000000000000000000000000000000000000000000000000000000000060368201527fffffff000000000000000000000000000000000000000000000000000000000060e886901b166037820152603a016109b1565b63ffffffff8411610dc2576040517fda0000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f840000000000000000000000000000000000000000000000000000000000000060368201527fffffffff0000000000000000000000000000000000000000000000000000000060e086901b166037820152603b016109b1565b64ffffffffff8411610ea5576040517fdb0000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f850000000000000000000000000000000000000000000000000000000000000060368201527fffffffffff00000000000000000000000000000000000000000000000000000060d886901b166037820152603c016109b1565b65ffffffffffff8411610f89576040517fdc0000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f860000000000000000000000000000000000000000000000000000000000000060368201527fffffffffffff000000000000000000000000000000000000000000000000000060d086901b166037820152603d016109b1565b66ffffffffffffff841161106e576040517fdd0000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f870000000000000000000000000000000000000000000000000000000000000060368201527fffffffffffffff0000000000000000000000000000000000000000000000000060c886901b166037820152603e016109b1565b6040517fde0000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f880000000000000000000000000000000000000000000000000000000000000060368201527fffffffffffffffff00000000000000000000000000000000000000000000000060c086901b166037820152603f0160405160208183030381529060405291505b5080516020909101209392505050565b60006104d86111e260408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b83611505565b600061126f61126860408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b8484610539565b9392505050565b600061126f83837f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed6119ed565b60008451602086018451f090506112b9816123d3565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f4db17dd5e4732fb6da34a148104a592783ca119a1e7bb8829eba6cbadef0b51190600090a26000808273ffffffffffffffffffffffffffffffffffffffff168560200151876040516113279190612d29565b60006040518083038185875af1925050503d8060008114611364576040519150601f19603f3d011682016040523d82523d6000602084013e611369565b606091505b5091509150816113c9577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed816040517fa57ca23900000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed1631156114fb578373ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed73ffffffffffffffffffffffffffffffffffffffff163160405160006040518083038185875af1925050503d8060008114611495576040519150601f19603f3d011682016040523d82523d6000602084013e61149a565b606091505b509092509050816114fb577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed816040517fc2b3f44500000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b5050949350505050565b600080611511846120db565b905060006040518060400160405280601081526020017f67363d3d37363d34f03d5260086018f30000000000000000000000000000000081525090506000828251602084016000f5905073ffffffffffffffffffffffffffffffffffffffff81166115e0576040517fc05cee7a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b604051839073ffffffffffffffffffffffffffffffffffffffff8316907f2feea65dd4e9f9cbd86b74b7734210c59a1b2981b5b137bd0ee3e208200c906790600090a361162c83610823565b935060008173ffffffffffffffffffffffffffffffffffffffff1634876040516116569190612d29565b60006040518083038185875af1925050503d8060008114611693576040519150601f19603f3d011682016040523d82523d6000602084013e611698565b606091505b505090506116a681866124ff565b60405173ffffffffffffffffffffffffffffffffffffffff8616907f4db17dd5e4732fb6da34a148104a592783ca119a1e7bb8829eba6cbadef0b51190600090a25050505092915050565b6000806116fd876120db565b9050808651602088018651f59150611714826123d3565b604051819073ffffffffffffffffffffffffffffffffffffffff8416907fb8fda7e00c6b06a2b54e58521bc5894fee35f1090e5a3bb6390bfe2b98b497f790600090a36000808373ffffffffffffffffffffffffffffffffffffffff168660200151886040516117849190612d29565b60006040518083038185875af1925050503d80600081146117c1576040519150601f19603f3d011682016040523d82523d6000602084013e6117c6565b606091505b509150915081611826577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed816040517fa57ca23900000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed163115611958578473ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed73ffffffffffffffffffffffffffffffffffffffff163160405160006040518083038185875af1925050503d80600081146118f2576040519150601f19603f3d011682016040523d82523d6000602084013e6118f7565b606091505b50909250905081611958577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed816040517fc2b3f44500000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b50505095945050505050565b60006107b36119e460408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b858585336116f1565b6000604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b600080611a23876120db565b905060006040518060400160405280601081526020017f67363d3d37363d34f03d5260086018f30000000000000000000000000000000081525090506000828251602084016000f5905073ffffffffffffffffffffffffffffffffffffffff8116611af2576040517fc05cee7a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b604051839073ffffffffffffffffffffffffffffffffffffffff8316907f2feea65dd4e9f9cbd86b74b7734210c59a1b2981b5b137bd0ee3e208200c906790600090a3611b3e83610823565b935060008173ffffffffffffffffffffffffffffffffffffffff1687600001518a604051611b6c9190612d29565b60006040518083038185875af1925050503d8060008114611ba9576040519150601f19603f3d011682016040523d82523d6000602084013e611bae565b606091505b50509050611bbc81866124ff565b60405173ffffffffffffffffffffffffffffffffffffffff8616907f4db17dd5e4732fb6da34a148104a592783ca119a1e7bb8829eba6cbadef0b51190600090a260608573ffffffffffffffffffffffffffffffffffffffff1688602001518a604051611c299190612d29565b60006040518083038185875af1925050503d8060008114611c66576040519150601f19603f3d011682016040523d82523d6000602084013e611c6b565b606091505b50909250905081611ccc577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed816040517fa57ca23900000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed163115611dfe578673ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed73ffffffffffffffffffffffffffffffffffffffff163160405160006040518083038185875af1925050503d8060008114611d98576040519150601f19603f3d011682016040523d82523d6000602084013e611d9d565b606091505b50909250905081611dfe577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed816040517fc2b3f44500000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b505050505095945050505050565b60006103dd611e8c60408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b868686866116f1565b60006103dd85858585336116f1565b60006103dd611f2460408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b86868686611a17565b6000808360601b90506040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528160148201527f5af43d82803e903d91602b57fd5bf3000000000000000000000000000000000060288201526037816000f092505073ffffffffffffffffffffffffffffffffffffffff8216612016576040517fc05cee7a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b60405173ffffffffffffffffffffffffffffffffffffffff8316907f4db17dd5e4732fb6da34a148104a592783ca119a1e7bb8829eba6cbadef0b51190600090a26000808373ffffffffffffffffffffffffffffffffffffffff1634866040516120809190612d29565b60006040518083038185875af1925050503d80600081146120bd576040519150601f19603f3d011682016040523d82523d6000602084013e6120c2565b606091505b50915091506120d282828861247d565b50505092915050565b60008060006120e9846125b3565b9092509050600082600281111561210257612102612e02565b1480156121205750600081600281111561211e5761211e612e02565b145b1561215e57604080513360208201524691810191909152606081018590526080016040516020818303038152906040528051906020012092506123cc565b600082600281111561217257612172612e02565b1480156121905750600181600281111561218e5761218e612e02565b145b156121b0576121a9338560009182526020526040902090565b92506123cc565b60008260028111156121c4576121c4612e02565b03612233576040517f13b3a2a100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b600182600281111561224757612247612e02565b1480156122655750600081600281111561226357612263612e02565b145b1561227e576121a9468560009182526020526040902090565b600182600281111561229257612292612e02565b1480156122b0575060028160028111156122ae576122ae612e02565b145b1561231f576040517f13b3a2a100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b61239a60408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b84036123a657836123c9565b604080516020810186905201604051602081830303815290604052805190602001205b92505b5050919050565b73ffffffffffffffffffffffffffffffffffffffff8116158061240b575073ffffffffffffffffffffffffffffffffffffffff81163b155b1561247a576040517fc05cee7a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b50565b82158061249f575073ffffffffffffffffffffffffffffffffffffffff81163b155b156124fa577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed826040517fa57ca23900000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b505050565b811580612520575073ffffffffffffffffffffffffffffffffffffffff8116155b80612540575073ffffffffffffffffffffffffffffffffffffffff81163b155b156125af576040517fc05cee7a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b5050565b600080606083901c3314801561261057508260141a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167f0100000000000000000000000000000000000000000000000000000000000000145b1561262057506000905080915091565b606083901c3314801561265a57507fff00000000000000000000000000000000000000000000000000000000000000601484901a60f81b16155b1561266b5750600090506001915091565b33606084901c036126825750600090506002915091565b606083901c1580156126db57508260141a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167f0100000000000000000000000000000000000000000000000000000000000000145b156126ec5750600190506000915091565b606083901c15801561272557507fff00000000000000000000000000000000000000000000000000000000000000601484901a60f81b16155b1561273557506001905080915091565b606083901c61274a5750600190506002915091565b8260141a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167f0100000000000000000000000000000000000000000000000000000000000000036127a55750600290506000915091565b8260141a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166000036127e15750600290506001915091565b506002905080915091565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261282c57600080fd5b813567ffffffffffffffff80821115612847576128476127ec565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561288d5761288d6127ec565b816040528381528660208588010111156128a657600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000604082840312156128d857600080fd5b6040516040810181811067ffffffffffffffff821117156128fb576128fb6127ec565b604052823581526020928301359281019290925250919050565b60008060008060a0858703121561292b57600080fd5b84359350602085013567ffffffffffffffff8082111561294a57600080fd5b6129568883890161281b565b9450604087013591508082111561296c57600080fd5b506129798782880161281b565b92505061298986606087016128c6565b905092959194509250565b600080604083850312156129a757600080fd5b82359150602083013567ffffffffffffffff8111156129c557600080fd5b6129d18582860161281b565b9150509250929050565b6000602082840312156129ed57600080fd5b813567ffffffffffffffff811115612a0457600080fd5b6107b38482850161281b565b803573ffffffffffffffffffffffffffffffffffffffff81168114612a3457600080fd5b919050565b600080600060608486031215612a4e57600080fd5b83359250612a5e60208501612a10565b9150604084013567ffffffffffffffff811115612a7a57600080fd5b612a868682870161281b565b9150509250925092565b600060208284031215612aa257600080fd5b5035919050565b600080600060808486031215612abe57600080fd5b833567ffffffffffffffff80821115612ad657600080fd5b612ae28783880161281b565b94506020860135915080821115612af857600080fd5b50612b058682870161281b565b925050612b1585604086016128c6565b90509250925092565b60008060408385031215612b3157600080fd5b82359150612b4160208401612a10565b90509250929050565b60008060408385031215612b5d57600080fd5b612b6683612a10565b946020939093013593505050565b60008060408385031215612b8757600080fd5b612b9083612a10565b9150602083013567ffffffffffffffff8111156129c557600080fd5b60008060408385031215612bbf57600080fd5b50508035926020909101359150565b60008060008060a08587031215612be457600080fd5b843567ffffffffffffffff80821115612bfc57600080fd5b612c088883890161281b565b95506020870135915080821115612c1e57600080fd5b50612c2b8782880161281b565b935050612c3b86604087016128c6565b915061298960808601612a10565b600080600080600060c08688031215612c6157600080fd5b85359450602086013567ffffffffffffffff80821115612c8057600080fd5b612c8c89838a0161281b565b95506040880135915080821115612ca257600080fd5b50612caf8882890161281b565b935050612cbf87606088016128c6565b9150612ccd60a08701612a10565b90509295509295909350565b600080600060608486031215612cee57600080fd5b8335925060208401359150612b1560408501612a10565b60005b83811015612d20578181015183820152602001612d08565b50506000910152565b60008251612d3b818460208701612d05565b9190910192915050565b67ffffffffffffffff828116828216039080821115612d8d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5092915050565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260008251806040840152612dcf816060850160208701612d05565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016060019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c6343000817000a"},"0xca11bde05977b3631167028862be2a173976ca11":{"nonce":"0x1","balance":"0x0","code":"0x6080604052600436106100f35760003560e01c80634d2301cc1161008a578063a8b0574e11610059578063a8b0574e1461025a578063bce38bd714610275578063c3077fa914610288578063ee82ac5e1461029b57600080fd5b80634d2301cc146101ec57806372425d9d1461022157806382ad56cb1461023457806386d516e81461024757600080fd5b80633408e470116100c65780633408e47014610191578063399542e9146101a45780633e64a696146101c657806342cbb15c146101d957600080fd5b80630f28c97d146100f8578063174dea711461011a578063252dba421461013a57806327e86d6e1461015b575b600080fd5b34801561010457600080fd5b50425b6040519081526020015b60405180910390f35b61012d610128366004610a85565b6102ba565b6040516101119190610bbe565b61014d610148366004610a85565b6104ef565b604051610111929190610bd8565b34801561016757600080fd5b50437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0140610107565b34801561019d57600080fd5b5046610107565b6101b76101b2366004610c60565b610690565b60405161011193929190610cba565b3480156101d257600080fd5b5048610107565b3480156101e557600080fd5b5043610107565b3480156101f857600080fd5b50610107610207366004610ce2565b73ffffffffffffffffffffffffffffffffffffffff163190565b34801561022d57600080fd5b5044610107565b61012d610242366004610a85565b6106ab565b34801561025357600080fd5b5045610107565b34801561026657600080fd5b50604051418152602001610111565b61012d610283366004610c60565b61085a565b6101b7610296366004610a85565b610a1a565b3480156102a757600080fd5b506101076102b6366004610d18565b4090565b60606000828067ffffffffffffffff8111156102d8576102d8610d31565b60405190808252806020026020018201604052801561031e57816020015b6040805180820190915260008152606060208201528152602001906001900390816102f65790505b5092503660005b8281101561047757600085828151811061034157610341610d60565b6020026020010151905087878381811061035d5761035d610d60565b905060200281019061036f9190610d8f565b6040810135958601959093506103886020850185610ce2565b73ffffffffffffffffffffffffffffffffffffffff16816103ac6060870187610dcd565b6040516103ba929190610e32565b60006040518083038185875af1925050503d80600081146103f7576040519150601f19603f3d011682016040523d82523d6000602084013e6103fc565b606091505b50602080850191909152901515808452908501351761046d577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260846000fd5b5050600101610325565b508234146104e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d756c746963616c6c333a2076616c7565206d69736d6174636800000000000060448201526064015b60405180910390fd5b50505092915050565b436060828067ffffffffffffffff81111561050c5761050c610d31565b60405190808252806020026020018201604052801561053f57816020015b606081526020019060019003908161052a5790505b5091503660005b8281101561068657600087878381811061056257610562610d60565b90506020028101906105749190610e42565b92506105836020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166105a66020850185610dcd565b6040516105b4929190610e32565b6000604051808303816000865af19150503d80600081146105f1576040519150601f19603f3d011682016040523d82523d6000602084013e6105f6565b606091505b5086848151811061060957610609610d60565b602090810291909101015290508061067d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b50600101610546565b5050509250929050565b43804060606106a086868661085a565b905093509350939050565b6060818067ffffffffffffffff8111156106c7576106c7610d31565b60405190808252806020026020018201604052801561070d57816020015b6040805180820190915260008152606060208201528152602001906001900390816106e55790505b5091503660005b828110156104e657600084828151811061073057610730610d60565b6020026020010151905086868381811061074c5761074c610d60565b905060200281019061075e9190610e76565b925061076d6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166107906040850185610dcd565b60405161079e929190610e32565b6000604051808303816000865af19150503d80600081146107db576040519150601f19603f3d011682016040523d82523d6000602084013e6107e0565b606091505b506020808401919091529015158083529084013517610851577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260646000fd5b50600101610714565b6060818067ffffffffffffffff81111561087657610876610d31565b6040519080825280602002602001820160405280156108bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816108945790505b5091503660005b82811015610a105760008482815181106108df576108df610d60565b602002602001015190508686838181106108fb576108fb610d60565b905060200281019061090d9190610e42565b925061091c6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff1661093f6020850185610dcd565b60405161094d929190610e32565b6000604051808303816000865af19150503d806000811461098a576040519150601f19603f3d011682016040523d82523d6000602084013e61098f565b606091505b506020830152151581528715610a07578051610a07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b506001016108c3565b5050509392505050565b6000806060610a2b60018686610690565b919790965090945092505050565b60008083601f840112610a4b57600080fd5b50813567ffffffffffffffff811115610a6357600080fd5b6020830191508360208260051b8501011115610a7e57600080fd5b9250929050565b60008060208385031215610a9857600080fd5b823567ffffffffffffffff811115610aaf57600080fd5b610abb85828601610a39565b90969095509350505050565b6000815180845260005b81811015610aed57602081850181015186830182015201610ad1565b81811115610aff576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b84811015610bb1578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051151584528401516040858501819052610b9d81860183610ac7565b9a86019a9450505090830190600101610b4f565b5090979650505050505050565b602081526000610bd16020830184610b32565b9392505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610c52577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610c40868351610ac7565b95509284019290840190600101610c06565b509398975050505050505050565b600080600060408486031215610c7557600080fd5b83358015158114610c8557600080fd5b9250602084013567ffffffffffffffff811115610ca157600080fd5b610cad86828701610a39565b9497909650939450505050565b838152826020820152606060408201526000610cd96060830184610b32565b95945050505050565b600060208284031215610cf457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610bd157600080fd5b600060208284031215610d2a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112610dc357600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610e0257600080fd5b83018035915067ffffffffffffffff821115610e1d57600080fd5b602001915036819003821315610a7e57600080fd5b8183823760009101908152919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610dc357600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112610dc357600080fdfea2646970667358221220bb2b5c71a328032f97c676ae39a1ec2148d3e5d6f73d95e9b17910152d61f16264736f6c634300080c0033"},"0xdec0000000000000000000000000000000000000":{"nonce":"0x0","balance":"0x0","code":"0xef"},"0xfeec000000000000000000000000000000000000":{"nonce":"0x0","balance":"0x0","code":"0xef","storage":{"0xabd7b398c2237712843e3e780dcd40dfb99446b30666f04c025da4efa5ce5177":"0x0000000000000000000000000000000000000000000000000000000000000000"}}},"baseFeePerGas":"0x2540be400"} \ No newline at end of file +{ + "config": { + "chainId": 1337, + "homesteadBlock": 0, + "daoForkSupport": false, + "eip150Block": 0, + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "mergeNetsplitBlock": 0, + "shanghaiTime": 0, + "cancunTime": 0, + "pragueTime": 0, + "osakaTime": 0, + "terminalTotalDifficulty": 0, + "terminalTotalDifficultyPassed": true, + "depositContractAddress": "0x0000000000000000000000000000000000000000" + }, + "nonce": "0x42", + "timestamp": "0x0", + "extraData": "0x74656d706f2d7a6f6e652d67656e65736973", + "gasLimit": "0x1c9c380", + "difficulty": "0x0", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "0x0000000000000000000000000000000000000000": { + "nonce": "0x1", + "balance": "0x0" + }, + "0x000000000022d473030f116ddee9f6b43ac78ba3": { + "nonce": "0x1", + "balance": "0x0", + "code": "0x6040608081526004908136101561001557600080fd5b600090813560e01c80630d58b1db1461126c578063137c29fe146110755780632a2d80d114610db75780632b67b57014610bde57806330f28b7a14610ade5780633644e51514610a9d57806336c7851614610a285780633ff9dcb1146109a85780634fe02b441461093f57806365d9723c146107ac57806387517c451461067a578063927da105146105c3578063cc53287f146104a3578063edd9444b1461033a5763fe8ec1a7146100c657600080fd5b346103365760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103365767ffffffffffffffff833581811161033257610114903690860161164b565b60243582811161032e5761012b903690870161161a565b6101336114e6565b9160843585811161032a5761014b9036908a016115c1565b98909560a43590811161032657610164913691016115c1565b969095815190610173826113ff565b606b82527f5065726d697442617463685769746e6573735472616e7366657246726f6d285460208301527f6f6b656e5065726d697373696f6e735b5d207065726d69747465642c61646472838301527f657373207370656e6465722c75696e74323536206e6f6e63652c75696e74323560608301527f3620646561646c696e652c000000000000000000000000000000000000000000608083015282519a8b9181610222602085018096611f93565b918237018a8152039961025b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09b8c8101835282611437565b5190209085515161026b81611ebb565b908a5b8181106102f95750506102f6999a6102ed9183516102a081610294602082018095611f66565b03848101835282611437565b519020602089810151858b015195519182019687526040820192909252336060820152608081019190915260a081019390935260643560c08401528260e081015b03908101835282611437565b51902093611cf7565b80f35b8061031161030b610321938c5161175e565b51612054565b61031b828661175e565b52611f0a565b61026e565b8880fd5b8780fd5b8480fd5b8380fd5b5080fd5b5091346103365760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103365767ffffffffffffffff9080358281116103325761038b903690830161164b565b60243583811161032e576103a2903690840161161a565b9390926103ad6114e6565b9160643590811161049f576103c4913691016115c1565b949093835151976103d489611ebb565b98885b81811061047d5750506102f697988151610425816103f9602082018095611f66565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282611437565b5190206020860151828701519083519260208401947ffcf35f5ac6a2c28868dc44c302166470266239195f02b0ee408334829333b7668652840152336060840152608083015260a082015260a081526102ed8161141b565b808b61031b8261049461030b61049a968d5161175e565b9261175e565b6103d7565b8680fd5b5082346105bf57602090817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103325780359067ffffffffffffffff821161032e576104f49136910161161a565b929091845b848110610504578580f35b8061051a610515600193888861196c565b61197c565b61052f84610529848a8a61196c565b0161197c565b3389528385528589209173ffffffffffffffffffffffffffffffffffffffff80911692838b528652868a20911690818a5285528589207fffffffffffffffffffffffff000000000000000000000000000000000000000081541690558551918252848201527f89b1add15eff56b3dfe299ad94e01f2b52fbcb80ae1a3baea6ae8c04cb2b98a4853392a2016104f9565b8280fd5b50346103365760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033657610676816105ff6114a0565b936106086114c3565b6106106114e6565b73ffffffffffffffffffffffffffffffffffffffff968716835260016020908152848420928816845291825283832090871683528152919020549251938316845260a083901c65ffffffffffff169084015260d09190911c604083015281906060820190565b0390f35b50346103365760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610336576106b26114a0565b906106bb6114c3565b916106c46114e6565b65ffffffffffff926064358481169081810361032a5779ffffffffffff0000000000000000000000000000000000000000947fda9fa7c1b00402c17d0161b249b1ab8bbec047c5a52207b9c112deffd817036b94338a5260016020527fffffffffffff0000000000000000000000000000000000000000000000000000858b209873ffffffffffffffffffffffffffffffffffffffff809416998a8d5260205283878d209b169a8b8d52602052868c209486156000146107a457504216925b8454921697889360a01b16911617179055815193845260208401523392a480f35b905092610783565b5082346105bf5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf576107e56114a0565b906107ee6114c3565b9265ffffffffffff604435818116939084810361032a57338852602091600183528489209673ffffffffffffffffffffffffffffffffffffffff80911697888b528452858a20981697888a5283528489205460d01c93848711156109175761ffff9085840316116108f05750907f55eb90d810e1700b35a8e7e25395ff7f2b2259abd7415ca2284dfb1c246418f393929133895260018252838920878a528252838920888a5282528389209079ffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffff000000000000000000000000000000000000000000000000000083549260d01b16911617905582519485528401523392a480f35b84517f24d35a26000000000000000000000000000000000000000000000000000000008152fd5b5084517f756688fe000000000000000000000000000000000000000000000000000000008152fd5b503461033657807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610336578060209273ffffffffffffffffffffffffffffffffffffffff61098f6114a0565b1681528084528181206024358252845220549051908152f35b5082346105bf57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf577f3704902f963766a4e561bbaab6e6cdc1b1dd12f6e9e99648da8843b3f46b918d90359160243533855284602052818520848652602052818520818154179055815193845260208401523392a280f35b8234610a9a5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a9a57610a606114a0565b610a686114c3565b610a706114e6565b6064359173ffffffffffffffffffffffffffffffffffffffff8316830361032e576102f6936117a1565b80fd5b503461033657817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033657602090610ad7611b1e565b9051908152f35b508290346105bf576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf57610b1a3661152a565b90807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c36011261033257610b4c611478565b9160e43567ffffffffffffffff8111610bda576102f694610b6f913691016115c1565b939092610b7c8351612054565b6020840151828501519083519260208401947f939c21a48a8dbe3a9a2404a1d46691e4d39f6583d6ec6b35714604c986d801068652840152336060840152608083015260a082015260a08152610bd18161141b565b51902091611c25565b8580fd5b509134610336576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033657610c186114a0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc360160c08112610332576080855191610c51836113e3565b1261033257845190610c6282611398565b73ffffffffffffffffffffffffffffffffffffffff91602435838116810361049f578152604435838116810361049f57602082015265ffffffffffff606435818116810361032a5788830152608435908116810361049f576060820152815260a435938285168503610bda576020820194855260c4359087830182815260e43567ffffffffffffffff811161032657610cfe90369084016115c1565b929093804211610d88575050918591610d786102f6999a610d7e95610d238851611fbe565b90898c511690519083519260208401947ff3841cd1ff0085026a6327b620b67997ce40f282c88a8e905a7a5626e310f3d086528401526060830152608082015260808152610d70816113ff565b519020611bd9565b916120c7565b519251169161199d565b602492508a51917fcd21db4f000000000000000000000000000000000000000000000000000000008352820152fd5b5091346103365760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc93818536011261033257610df36114a0565b9260249081359267ffffffffffffffff9788851161032a578590853603011261049f578051978589018981108282111761104a578252848301358181116103265785019036602383011215610326578382013591610e50836115ef565b90610e5d85519283611437565b838252602093878584019160071b83010191368311611046578801905b828210610fe9575050508a526044610e93868801611509565b96838c01978852013594838b0191868352604435908111610fe557610ebb90369087016115c1565b959096804211610fba575050508998995151610ed681611ebb565b908b5b818110610f9757505092889492610d7892610f6497958351610f02816103f98682018095611f66565b5190209073ffffffffffffffffffffffffffffffffffffffff9a8b8b51169151928551948501957faf1b0d30d2cab0380e68f0689007e3254993c596f2fdd0aaa7f4d04f794408638752850152830152608082015260808152610d70816113ff565b51169082515192845b848110610f78578580f35b80610f918585610f8b600195875161175e565b5161199d565b01610f6d565b80610311610fac8e9f9e93610fb2945161175e565b51611fbe565b9b9a9b610ed9565b8551917fcd21db4f000000000000000000000000000000000000000000000000000000008352820152fd5b8a80fd5b6080823603126110465785608091885161100281611398565b61100b85611509565b8152611018838601611509565b838201526110278a8601611607565b8a8201528d611037818701611607565b90820152815201910190610e7a565b8c80fd5b84896041867f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5082346105bf576101407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf576110b03661152a565b91807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c360112610332576110e2611478565b67ffffffffffffffff93906101043585811161049f5761110590369086016115c1565b90936101243596871161032a57611125610bd1966102f6983691016115c1565b969095825190611134826113ff565b606482527f5065726d69745769746e6573735472616e7366657246726f6d28546f6b656e5060208301527f65726d697373696f6e73207065726d69747465642c6164647265737320737065848301527f6e6465722c75696e74323536206e6f6e63652c75696e7432353620646561646c60608301527f696e652c0000000000000000000000000000000000000000000000000000000060808301528351948591816111e3602085018096611f93565b918237018b8152039361121c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe095868101835282611437565b5190209261122a8651612054565b6020878101518589015195519182019687526040820192909252336060820152608081019190915260a081019390935260e43560c08401528260e081016102e1565b5082346105bf576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033257813567ffffffffffffffff92838211610bda5736602383011215610bda5781013592831161032e576024906007368386831b8401011161049f57865b8581106112e5578780f35b80821b83019060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc83360301126103265761139288876001946060835161132c81611398565b611368608461133c8d8601611509565b9485845261134c60448201611509565b809785015261135d60648201611509565b809885015201611509565b918291015273ffffffffffffffffffffffffffffffffffffffff80808093169516931691166117a1565b016112da565b6080810190811067ffffffffffffffff8211176113b457604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff8211176113b457604052565b60a0810190811067ffffffffffffffff8211176113b457604052565b60c0810190811067ffffffffffffffff8211176113b457604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176113b457604052565b60c4359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b600080fd5b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b6044359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc01906080821261149b576040805190611563826113e3565b8082941261149b57805181810181811067ffffffffffffffff8211176113b457825260043573ffffffffffffffffffffffffffffffffffffffff8116810361149b578152602435602082015282526044356020830152606435910152565b9181601f8401121561149b5782359167ffffffffffffffff831161149b576020838186019501011161149b57565b67ffffffffffffffff81116113b45760051b60200190565b359065ffffffffffff8216820361149b57565b9181601f8401121561149b5782359167ffffffffffffffff831161149b576020808501948460061b01011161149b57565b91909160608184031261149b576040805191611666836113e3565b8294813567ffffffffffffffff9081811161149b57830182601f8201121561149b578035611693816115ef565b926116a087519485611437565b818452602094858086019360061b8501019381851161149b579086899897969594939201925b8484106116e3575050505050855280820135908501520135910152565b90919293949596978483031261149b578851908982019082821085831117611730578a928992845261171487611509565b81528287013583820152815201930191908897969594936116c6565b602460007f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b80518210156117725760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b92919273ffffffffffffffffffffffffffffffffffffffff604060008284168152600160205282828220961695868252602052818120338252602052209485549565ffffffffffff8760a01c16804211611884575082871696838803611812575b5050611810955016926118b5565b565b878484161160001461184f57602488604051907ff96fb0710000000000000000000000000000000000000000000000000000000082526004820152fd5b7fffffffffffffffffffffffff000000000000000000000000000000000000000084846118109a031691161790553880611802565b602490604051907fd81b2f2e0000000000000000000000000000000000000000000000000000000082526004820152fd5b9060006064926020958295604051947f23b872dd0000000000000000000000000000000000000000000000000000000086526004860152602485015260448401525af13d15601f3d116001600051141617161561190e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152fd5b91908110156117725760061b0190565b3573ffffffffffffffffffffffffffffffffffffffff8116810361149b5790565b9065ffffffffffff908160608401511673ffffffffffffffffffffffffffffffffffffffff908185511694826020820151169280866040809401511695169560009187835260016020528383208984526020528383209916988983526020528282209184835460d01c03611af5579185611ace94927fc6a377bfc4eb120024a8ac08eef205be16b817020812c73223e81d1bdb9708ec98979694508715600014611ad35779ffffffffffff00000000000000000000000000000000000000009042165b60a01b167fffffffffffff00000000000000000000000000000000000000000000000000006001860160d01b1617179055519384938491604091949373ffffffffffffffffffffffffffffffffffffffff606085019616845265ffffffffffff809216602085015216910152565b0390a4565b5079ffffffffffff000000000000000000000000000000000000000087611a60565b600484517f756688fe000000000000000000000000000000000000000000000000000000008152fd5b467f000000000000000000000000000000000000000000000000000000000000053903611b69577f1f520b5ee38ad937955892c3dfc7055e8eeb515d905781b6951e4c687917c53090565b60405160208101907f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86682527f9ac997416e8ff9d2ff6bebeb7149f65cdae5e32e2b90440b566bb3044041d36a604082015246606082015230608082015260808152611bd3816113ff565b51902090565b611be1611b1e565b906040519060208201927f190100000000000000000000000000000000000000000000000000000000000084526022830152604282015260428152611bd381611398565b9192909360a435936040840151804211611cc65750602084510151808611611c955750918591610d78611c6594611c60602088015186611e47565b611bd9565b73ffffffffffffffffffffffffffffffffffffffff809151511692608435918216820361149b57611810936118b5565b602490604051907f3728b83d0000000000000000000000000000000000000000000000000000000082526004820152fd5b602490604051907fcd21db4f0000000000000000000000000000000000000000000000000000000082526004820152fd5b959093958051519560409283830151804211611e175750848803611dee57611d2e918691610d7860209b611c608d88015186611e47565b60005b868110611d42575050505050505050565b611d4d81835161175e565b5188611d5a83878a61196c565b01359089810151808311611dbe575091818888886001968596611d84575b50505050505001611d31565b611db395611dad9273ffffffffffffffffffffffffffffffffffffffff6105159351169561196c565b916118b5565b803888888883611d78565b6024908651907f3728b83d0000000000000000000000000000000000000000000000000000000082526004820152fd5b600484517fff633a38000000000000000000000000000000000000000000000000000000008152fd5b6024908551907fcd21db4f0000000000000000000000000000000000000000000000000000000082526004820152fd5b9073ffffffffffffffffffffffffffffffffffffffff600160ff83161b9216600052600060205260406000209060081c6000526020526040600020818154188091551615611e9157565b60046040517f756688fe000000000000000000000000000000000000000000000000000000008152fd5b90611ec5826115ef565b611ed26040519182611437565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611f0082946115ef565b0190602036910137565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611f375760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b805160208092019160005b828110611f7f575050505090565b835185529381019392810192600101611f71565b9081519160005b838110611fab575050016000815290565b8060208092840101518185015201611f9a565b60405160208101917f65626cad6cb96493bf6f5ebea28756c966f023ab9e8a83a7101849d5573b3678835273ffffffffffffffffffffffffffffffffffffffff8082511660408401526020820151166060830152606065ffffffffffff9182604082015116608085015201511660a082015260a0815260c0810181811067ffffffffffffffff8211176113b45760405251902090565b6040516020808201927f618358ac3db8dc274f0cd8829da7e234bd48cd73c4a740aede1adec9846d06a1845273ffffffffffffffffffffffffffffffffffffffff81511660408401520151606082015260608152611bd381611398565b919082604091031261149b576020823592013590565b6000843b61222e5750604182036121ac576120e4828201826120b1565b939092604010156117725760209360009360ff6040608095013560f81c5b60405194855216868401526040830152606082015282805260015afa156121a05773ffffffffffffffffffffffffffffffffffffffff806000511691821561217657160361214c57565b60046040517f815e1d64000000000000000000000000000000000000000000000000000000008152fd5b60046040517f8baa579f000000000000000000000000000000000000000000000000000000008152fd5b6040513d6000823e3d90fd5b60408203612204576121c0918101906120b1565b91601b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84169360ff1c019060ff8211611f375760209360009360ff608094612102565b60046040517f4be6321b000000000000000000000000000000000000000000000000000000008152fd5b929391601f928173ffffffffffffffffffffffffffffffffffffffff60646020957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0604051988997889687947f1626ba7e000000000000000000000000000000000000000000000000000000009e8f8752600487015260406024870152816044870152868601378b85828601015201168101030192165afa9081156123a857829161232a575b507fffffffff000000000000000000000000000000000000000000000000000000009150160361230057565b60046040517fb0669cbc000000000000000000000000000000000000000000000000000000008152fd5b90506020813d82116123a0575b8161234460209383611437565b810103126103365751907fffffffff0000000000000000000000000000000000000000000000000000000082168203610a9a57507fffffffff0000000000000000000000000000000000000000000000000000000090386122d4565b3d9150612337565b6040513d84823e3d90fdfea164736f6c6343000811000a" + }, + "0x1c00000000000000000000000000000000000000": { + "nonce": "0x1", + "balance": "0x0", + "code": "0x60806040526004361015610011575f80fd5b5f3560e01c80631d04645f146101245780632245d0831461011f5780632e224dee1461011a5780633d7a27611461011557806346903867146101105780634732f8bb1461010b57806352d922a51461010657806358c3659914610101578063615cf854146100fc5780636aba6931146100f757806380a4cbc8146100f257806381e3da6b146100ed5780639a7361eb146100e8578063c334cd20146100e3578063f3b52855146100de578063f495be0b146100d95763fe770099146100d4575f80fd5b61052e565b610505565b6104dc565b6104bf565b6104a2565b610345565b610329565b6102b1565b61023a565b610214565b6101f7565b6101d1565b6101b1565b610194565b610177565b61014e565b3461014a575f36600319011261014a5760206001600160401b0360075416604051908152f35b5f80fd5b3461014a575f36600319011261014a5760206001600160401b0360015460401c16604051908152f35b3461014a575f36600319011261014a576020600454604051908152f35b3461014a575f36600319011261014a576020600954604051908152f35b3461014a575f36600319011261014a57602060075460c01c604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360085416604051908152f35b3461014a575f36600319011261014a576020600254604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360015416604051908152f35b3461014a575f36600319011261014a576003546040516001600160a01b039091168152602090f35b600435906001600160a01b038216820361014a57565b60206040818301928281528451809452019201905f5b81811061029b5750505090565b825184526020938401939092019160010161028e565b3461014a57604036600319011261014a576102ca610262565b6024356001600160401b03811161014a573660238201121561014a5780600401356001600160401b03811161014a573660248260051b8401011161014a57610325926024610319930190610655565b60405191829182610278565b0390f35b3461014a575f36600319011261014a5760205f54604051908152f35b3461014a57604036600319011261014a5761035e610262565b3360016007609a1b01141580610491575b80610480575b61041557600754604051631e7d027560e31b81526001600160a01b03909216600483015260248035908301526001600160401b0316604482015260208160648160046007609a1b015afa801561041057610325915f916103e1575b506040519081529081906020820190565b610403915060203d602011610409575b6103fb8183610742565b8101906107f6565b5f6103d0565b503d6103f1565b6107eb565b60405162461bcd60e51b815260206004820152603b60248201527f54656d706f53746174653a206f6e6c79207a6f6e652073797374656d20636f6e60448201527f7472616374732063616e20726561642054656d706f20737461746500000000006064820152608490fd5b503360036007609a1b011415610375565b503360026007609a1b01141561036f565b3461014a575f36600319011261014a576020600554604051908152f35b3461014a575f36600319011261014a576020600654604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360075460401c16604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360075460801c16604051908152f35b3461014a57602036600319011261014a576004356001600160401b03811161014a573660238201121561014a578060040135906001600160401b03821161014a57366024838301011161014a576007609a1b193301610646576105b26105ad5f54926105a26007546001600160401b031690565b946024369201610805565b6108c6565b60025403610637576001600160401b036105ec6105e06105da6007546001600160401b031690565b9361085e565b6001600160401b031690565b9116908103610628575f546004546040519081527fdd85219569c3c880f014955916f426d1ca039714b59ce33e24f151f155ac26b990602090a3005b631391e11b60e21b5f5260045ffd5b63591c836760e01b5f5260045ffd5b6303300c7360e31b5f5260045ffd5b91903360016007609a1b0114158061071d575b8061070c575b61041557600754604051632593f8c960e01b81526001600160a01b03909416600485015260606024850152606484018390526001600160401b03166001600160fb1b03831161014a578380926084925f9560051b8092858501376044830152810103018160046007609a1b015afa908115610410575f916106ed575090565b61070991503d805f833e6107018183610742565b810190610768565b90565b503360036007609a1b01141561066e565b503360026007609a1b011415610668565b634e487b7160e01b5f52604160045260245ffd5b90601f801991011681019081106001600160401b0382111761076357604052565b61072e565b60208183031261014a578051906001600160401b03821161014a57019080601f8301121561014a578151916001600160401b038311610763578260051b90604051936107b76020840186610742565b845260208085019282010192831161014a57602001905b8282106107db5750505090565b81518152602091820191016107ce565b6040513d5f823e3d90fd5b9081602091031261014a575190565b9291926001600160401b038211610763576040519161082e601f8201601f191660200184610742565b82948184528183011161014a578281602093845f960137010152565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b036001911601906001600160401b03821161087c57565b61084a565b906001820180921161087c57565b600101908160011161087c57565b906021820180921161087c57565b906015820180921161087c57565b9190820180921161087c57565b805160208201205f556108d881610c28565b80915015610ba85761098b61095a61091c836109166108fa6109939688610dd1565b6001600160401b03166001600160401b03196001541617600155565b85610ea6565b905061095461092b8287610dd1565b67ffffffffffffffff60401b6001549160401b169067ffffffffffffffff60401b191617600155565b84610ea6565b90506109856109698286610dd1565b6001600160401b03166001600160401b03196008541617600855565b83610ea6565b905082610d0e565b91908215610ba857610b77610b6f610b5b610b53610b1f610add610aa5610a74610a6c610a648b610a5e610a598f610a3c610a286109f16109e9846109e36109de610a50978b611020565b600255565b88610ea6565b905087610ea6565b9050610a22610a0082896110f0565b60018060a01b03166bffffffffffffffffffffffff60a01b6003541617600355565b86610ea6565b9050610916610a378288611020565b600455565b9050610954610a4b8287611020565b600555565b93849150611020565b600655565b8c610ea6565b90508b610ea6565b90508a610ea6565b9050610a9f610a83828c610dd1565b6001600160401b03166001600160401b03196007541617600755565b89610ea6565b90506109e3610ab4828b610dd1565b67ffffffffffffffff60401b6007549160401b169067ffffffffffffffff60401b191617600755565b9050610b19610aec828a610dd1565b6007805467ffffffffffffffff60801b191660809290921b67ffffffffffffffff60801b16919091179055565b87610ea6565b9050610a22610b2e8289610dd1565b600780546001600160c01b031660c09290921b6001600160c01b031916919091179055565b905085610ea6565b9050610954610b6a8287611020565b600955565b905083610ea6565b9050905b610b8581856108b9565b821015610ba257610b99610b859284610ea6565b90509150610b7b565b50505050565b6305787a5560e41b5f5260045ffd5b908151811015610bc8570160200190565b634e487b7160e01b5f52603260045260245ffd5b60ff60f6199116019060ff821161087c57565b60ff60bf199116019060ff821161087c57565b60ff607f199116019060ff821161087c57565b60ff60b6199116019060ff821161087c57565b805115610d0757610c53610c4d610c3f5f84610bb7565b516001600160f81b03191690565b60f81c90565b9060ff821660bf8111610c69575050505f905f90565b60f710610c8d5750610c7d610c8391610bef565b60ff1690565b906107095f610881565b9190610c7d610c9b91610bdc565b610cad81610ca85f610881565b6108b9565b835110610cff575f925f905b828210610ccf57505061070990610ca85f610881565b909360019060081b610cf6610c7d610c4d610c3f610cf08a610ca85f610881565b87610bb7565b17940190610cb9565b505f91508190565b505f905f90565b9190918051831015610cff57610d2a610c4d610c3f8584610bb7565b9060ff821660bf8111610d425750505090505f905f90565b60f710610d5f5750610d59610c7d61070992610bef565b92610881565b9290610c7d610d6d91610bdc565b90610d7b82610ca883610881565b845110610dc7575f935f905b838210610d9d57505090610ca861070992610881565b909460019060081b610dbe610c7d610c4d610c3f610cf08b610ca88a610881565b17950190610d87565b505090505f905f90565b8051821015610ba857610dea610c4d610c3f8484610bb7565b60ff81169290607f8411610dfe5750505090565b90919392608081145f14610e1457505f93505050565b60818110159081610e9a575b5015610ba857610c7d610e3291610c02565b90610e4082610ca883610881565b845110610ba85792905f935f925b828410610e5b5750505050565b90919294610e7660019167ffffffffffffff009060081b1690565b610e8f610c7d610c4d610c3f610cf08b610ca88a610881565b179501929190610e4e565b6088915011155f610e20565b9190918051831015610ba857610ec2610c4d610c3f8584610bb7565b9060ff8216607f8111610ee15750505090610edc90610881565b600191565b60b78111610f0c575050610efa610c7d61070992610c02565b610ca8610f068261088f565b94610881565b60bf8111610f78575090610c7d610f2291610c15565b5f915f905b828210610f4e57505090610ca882610ca8610f4884610ca86107099761088f565b96610881565b909260019060081b610f6f610c7d610c4d610c3f610cf089610ca88d610881565b17930190610f27565b60f710610f8f5750610efa610c7d61070992610bef565b90610c7d610f9c91610bdc565b5f915f905b828210610fc257505090610ca882610ca8610f4884610ca86107099761088f565b909260019060081b610fe3610c7d610c4d610c3f610cf089610ca88d610881565b17930190610fa1565b602003906020821161087c57565b5f1981019190821161087c57565b600381901b91906001600160fd1b0381160361087c57565b908151811015610ba85761103a610c4d610c3f8385610bb7565b60ff81169060a082036110615750506110528161089d565b825110610ba857016021015190565b909290607f84116110725750505090565b909192608081101590816110e4575b5015610ba857610c7d61109391610c02565b91826110a0575050505f90565b60208311610ba8576110b583610ca883610881565b825110610ba8576110d96110d460216001936110df9501015194610fec565b611008565b1b610ffa565b191690565b60b7915011155f611081565b908151811015610ba85760ff61110c610c4d610c3f8486610bb7565b1660948103611131575061111f816108ab565b825110610ba857016021015160601c90565b608014159150610ba89050575f9056fea264697066735822122080b308cfbaed22d64784e3d4fb6b484fd454359940ac664d9351ecac7847185e64736f6c63430008210033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0xb049644b1d5a0ec9d785dd48f95099e0f566112084acb1ba0814112209b432a1", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "0x1c00000000000000000000000000000000000001": { + "nonce": "0x1", + "balance": "0x0", + "code": "0x60806040526004361015610011575f80fd5b5f3560e01c80631fbb25ad1461007457806379502c551461006f57806382648c3b1461006a578063a21de6d914610065578063ce11e6ab146100605763d01e8d311461005b575f80fd5b61020e565b61016a565b610126565b61010a565b6100c6565b346100b8575f3660031901126100b8577f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b03166080908152602090f35b5f80fd5b5f9103126100b857565b346100b8575f3660031901126100b8576040517f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03168152602090f35b346100b8575f3660031901126100b85760205f54604051908152f35b346100b8575f3660031901126100b8576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346100b8575f3660031901126100b8576040517f0000000000000000000000001c000000000000000000000000000000000000026001600160a01b03168152602090f35b9181601f840112156100b8578235916001600160401b0383116100b8576020808501948460051b0101116100b857565b9181601f840112156100b8578235916001600160401b0383116100b85760208085019460c085020101116100b857565b346100b85760803660031901126100b8576004356001600160401b0381116100b857366023820112156100b8578060040135906001600160401b0382116100b85736602483830101116100b8576024356001600160401b0381116100b85761027a9036906004016101ae565b6044929192356001600160401b0381116100b85761029c9036906004016101de565b91606435946001600160401b0386116100b8576102cc966102c360249736906004016101ae565b97909601610a75565b005b634e487b7160e01b5f52604160045260245ffd5b60a081019081106001600160401b038211176102fd57604052565b6102ce565b60c081019081106001600160401b038211176102fd57604052565b90601f801991011681019081106001600160401b038211176102fd57604052565b6001600160a01b038116036100b857565b908160209103126100b857516103648161033e565b90565b6040513d5f823e3d90fd5b908060209392818452848401375f828201840152601f01601f1916010190565b916020610364938181520191610372565b634e487b7160e01b5f52603260045260245ffd5b91908110156103d95760051b81013590607e19813603018212156100b8570190565b6103a3565b356103648161033e565b903590601e19813603018212156100b857018035906001600160401b0382116100b8576020019181360383136100b857565b959391610446906104549461036499979360018060a01b03168952608060208a01526080890191610372565b918683036040880152610372565b926060818503910152610372565b94929093610480610364979561048e94606089526060890191610372565b918683036020880152610372565b926040818503910152610372565b91908110156103d95760051b81013590603e19813603018212156100b8570190565b600211156104c857565b634e487b7160e01b5f52602160045260245ffd5b3560028110156100b85790565b35906104f48261033e565b565b35906001600160801b03821682036100b857565b60ff8116036100b857565b6001600160401b0381116102fd57601f01601f191660200190565b35906001600160a01b0319821682036100b857565b35906001600160801b0319821682036100b857565b919060a0838203126100b85760405190610573826102e2565b81938035835260208101356105878161050a565b602084015260408101356001600160401b0381116100b857810182601f820112156100b8578035916105b883610515565b936105c6604051958661031d565b838552602084840101116100b8576080935f6020856106079682899701838601378301015260408601526105fc60608201610530565b606086015201610545565b910152565b6020818303126100b8578035906001600160401b0382116100b8570160c0818303126100b8576040519161063f83610302565b813561064a8161033e565b8352610658602083016104e9565b6020840152610669604083016104f6565b6040840152606082013560608401526080820135916001600160401b0383116100b85761069d60a0926106a894830161055a565b6080850152016104e9565b60a082015290565b634e487b7160e01b5f52601160045260245ffd5b5f1981146106d25760010190565b6106b0565b91908110156103d95760c0020190565b356103648161050a565b519081151582036100b857565b908160209103126100b857610364906106f1565b6040519061072160408361031d565b600d82526c65636965732d6165732d6b657960981b6020830152565b91906040838203126100b85782516001600160401b0381116100b857830181601f820112156100b85780519161077283610515565b90610780604051928361031d565b838252602084840101116100b8575f60208461036495828096018386015e8301015293016106f1565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b926108039060809360209397969786526bffffffffffffffffffffffff60a01b168386015260a0604086015260a08501906107a9565b83810360608501525f815201936001600160801b031916910152565b9060028210156104c85752565b92919060409061083d85600161081f565b6060602086015260018060a01b03815116606086015260018060a01b0360208201511660808601526001600160801b03828201511660a0860152606081015160c086015261090660a060808301519260c060e0890152835161012089015260ff6020850151166101408901526108c285850151836101608b01526101c08a01906107a9565b60608501516bffffffffffffffffffffffff841b166101808a01526080909401516001600160801b0319166101a089015201516001600160a01b0316610100870152565b930152565b6001600160a01b0390911681526001600160801b03909116602082015260400190565b6001600160a01b0391821681526001600160801b039092166020830152909116604082015260600190565b908160c09103126100b85760a06040519161097383610302565b803561097e8161033e565b8352602081013561098e8161033e565b602084015260408101356109a18161033e565b60408401526109b2606082016104f6565b60608401526080810135608084015201356106a88161033e565b610100810193929160e091906109e2825f61081f565b60018060a01b03815116602083015260018060a01b03602082015116604083015260018060a01b0360408201511660608301526001600160801b036060820151166080830152608081015160a083015260a0600180821b039101511660c08201520152565b908160209103126100b8575190565b908160209103126100b857516001600160401b03811681036100b85790565b9591949392969033151580611a3b575b611a2c577f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b031696873b156100b85760405163fe77009960e01b8152915f9183918291610add919060048401610392565b0381838b5af18015610c3c57611a18575b505f9492945b8181106118fd575050505f54925f915f915b878310610ca25750505003610c93576040516381e3da6b60e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166004808301919091526024820152602081604481865afa8015610c3c57610c76575b505f819055604051631014997960e31b815291602083600481845afa928315610c3c575f93610c41575b50602060049160405192838092631d04645f60e01b82525afa8015610c3c577f87977a3515c59199065d0e2d7837b95d8fcf5fb072c0321138df0786011e32c4926001600160401b03925f92610c07575b5060408051968752602087019190915291169390819081015b0390a3565b610c02919250610c2e9060203d602011610c35575b610c26818361031d565b810190610a56565b9190610be9565b503d610c1c565b610367565b6004919350610c67602091823d8411610c6f575b610c5f818361031d565b810190610a47565b939150610b98565b503d610c55565b610c8e9060203d602011610c6f57610c5f818361031d565b610b6e565b6361aba18160e11b5f5260045ffd5b909194610cb086898561049c565b610cb9816104dc565b610cc2816104be565b6110ba57610cd7816020610cdf9301906103e8565b810190610959565b90604051610d0481610cf6602082019486866109cc565b03601f19810183528261031d565b5190209560a0820191610d2c610d20845160018060a01b031690565b6001600160a01b031690565b15610fec578051610d4790610d20906001600160a01b031681565b604082018051909491906001600160a01b03166060840191610d7083516001600160801b031690565b91813b156100b8578c92610d9d925f92836040518096819582946340c10f1960e01b84526004840161090b565b03925af19081610fd8575b50610f1c575082516001600160a01b037f0000000000000000000000001c00000000000000000000000000000000000002811692911681516001600160801b031684519093906001600160a01b031690803b156100b857610e23945f8094604051978895869485936338b8fb9760e21b85526004850161092e565b03925af1958615610c3c57610ef68c947f3c1af70310b8c9d43b0a7207217f398e4a3114f1728987c40addb451399ac87c94600199610f02575b506020870151610eb490610ea690610e9890610e8a906001600160a01b031696516001600160a01b031690565b99516001600160a01b031690565b95516001600160801b031690565b91516001600160a01b031690565b906040519485948b8060a01b031698856001600160a01b03918216815291811660208301526001600160801b0390921660408201529116606082015260800190565b0390a35b019190610b06565b80610f105f610f169361031d565b806100bc565b5f610e5d565b60208401516001969492935090917fd5277bc9597c7da3fab9cdbba4de6005f48b9eb7389cf2389c4ea9eea3172c2191610f68906001600160a01b03165b95516001600160a01b031690565b8151610fd090608090610f8d906001600160a01b03165b97516001600160801b031690565b930151604080516001600160a01b0390981688526001600160801b0390941660208801529286019290925260a088901b8890039081169516939081906060820190565b0390a4610efa565b80610f105f610fe69361031d565b5f610da8565b805190925061100590610d20906001600160a01b031681565b6040830180519091906001600160a01b031690606085019161102e83516001600160801b031690565b823b156100b857611058925f92836040518096819582946340c10f1960e01b84526004840161090b565b03925af18015610c3c576001958b927fd5277bc9597c7da3fab9cdbba4de6005f48b9eb7389cf2389c4ea9eea3172c21926110a6575b506020810151610f68906001600160a01b0316610f5a565b80610f105f6110b49361031d565b5f61108e565b6110ce8160206110d69399949901906103e8565b81019061060c565b90858510156118ee576110f36110eb866106c4565b9587856106d7565b606083016111018151611afb565b9160808601926020608086611187875161112085825192015160ff1690565b9583359861112f8786016106e7565b604051635f8a996960e01b8152600481019490945260ff9889166024850152604484018b905288166064840152608483015290951660a48601529101803560c48501526020013560e484015282908190610104820190565b0381731c000000000000000000000000000000000001005afa908115610c3c575f916118c0575b50156118b157518251516040516bffffffffffffffffffffffff197f000000000000000000000000000000000000000000000000000000000000000060601b166020820152603481019290925260548083019190915281525f91611226919061121860748361031d565b611220610712565b90611c6c565b915160608101519092906001600160a01b03191690611273611258608060408701519601516001600160801b03191690565b60405163f4a7eb1360e01b81529586948594600486016107cd565b0381731c000000000000000000000000000000000001015afa8015610c3c575f915f9161188d575b5080611882575b1561187a576112b090611cd8565b906112c0610d20604085016103de565b6001600160a01b0390911614908161186c575b50975b6040516112ec81610cf66020820194888661082c565b5190209761156c575060a08201805161130d906001600160a01b0316610d20565b1561150157825161132890610d20906001600160a01b031681565b6020840180519094919291906001600160a01b0316604082019361135385516001600160801b031690565b91813b156100b8578c92611380925f92836040518096819582946340c10f1960e01b84526004840161090b565b03925af190816114ed575b506114ad575080516001600160a01b037f0000000000000000000000001c0000000000000000000000000000000000000281169116906113e36113d586516001600160801b031690565b94516001600160a01b031690565b90803b156100b85761140f945f8094604051978895869485936338b8fb9760e21b85526004850161092e565b03925af1908115610c3c5761147961146b61145d6001988e967f95705d99ac13cf82894fd274cd871942e6f301c98c186271337e8fedbbb9d7ea96611499575b50516001600160a01b031690565b92516001600160a01b031690565b94516001600160801b031690565b90611491604051928392898060a01b0316968361090b565b0390a3610efa565b80610f105f6114a79361031d565b5f61144f565b945160019592507f95705d99ac13cf82894fd274cd871942e6f301c98c186271337e8fedbbb9d7ea91906114799061146b906001600160a01b031661145d565b80610f105f6114fb9361031d565b5f61138b565b50815161151890610d20906001600160a01b031681565b602083018051909391906001600160a01b031691604081019261154284516001600160801b031690565b833b156100b85761140f935f92836040518097819582946340c10f1960e01b84526004840161090b565b60a083018051919391611587906001600160a01b0316610d20565b156117955781516115a290610d20906001600160a01b031681565b60408501946115b0866103de565b9060408501926115c784516001600160801b031690565b92813b156100b8578d936115f4925f92836040518096819582946340c10f1960e01b84526004840161090b565b03925af19081611781575b506116ee57505082516001600160a01b037f0000000000000000000000001c00000000000000000000000000000000000002811692911681516001600160801b031684519093906001600160a01b031690803b156100b85761167b945f8094604051978895869485936338b8fb9760e21b85526004850161092e565b03925af1958615610c3c576114918c947f3c1af70310b8c9d43b0a7207217f398e4a3114f1728987c40addb451399ac87c946001996116da575b506020870151610eb490610ea690610e9890610e8a906001600160a01b0316966103de565b80610f105f6116e89361031d565b5f6116b5565b7ffc236d1b4402e76c2b0a882db36ad3a6fb0f5b6b7edc8ae317d993f10434c4369192935084610fd0606061173e610f7f6113d5611738602060019e9c015160018060a01b031690565b9a6103de565b604080516001600160a01b0390991689526001600160801b0390911660208901529301359286019290925260a088901b8890039081169516939081906060820190565b80610f105f61178f9361031d565b5f6115ff565b5080519092906117af90610d20906001600160a01b031681565b9060408101916117be836103de565b9160408601926117d584516001600160801b031690565b833b156100b8576117ff935f92836040518097819582946340c10f1960e01b84526004840161090b565b03925af1908115610c3c576001968c937ffc236d1b4402e76c2b0a882db36ad3a6fb0f5b6b7edc8ae317d993f10434c43693611858575b50610fd0606061173e610f7f6113d5611738602087015160018060a01b031690565b80610f105f6118669361031d565b5f611836565b90506060820135145f6112d3565b505f976112d6565b5060408151146112a2565b90506118ab91503d805f833e6118a3818361031d565b81019061073d565b5f61129b565b63fb1f4a4960e01b5f5260045ffd5b6118e1915060203d81116118e7575b6118d9818361031d565b8101906106fe565b5f6111ae565b503d6118cf565b6351de8c1f60e01b5f5260045ffd5b61190b8183859896986103b7565b90611915826103de565b91602081019061192582826103e8565b9092604083019361193685856103e8565b91909760608601986119488a886103e8565b9061083f60921b3b156100b8575f9561197693604051998a9788976374ae5b3760e11b89526004890161041a565b03818361083f60921b5af18015610c3c576001967f4ac4dcc08b0c26c3fb6b58c64c1392b7934b1ce6b0382a5986ea5c3de795e053946119d9946119f893611a04575b506119e16119d06119c9836103de565b95836103e8565b969098836103e8565b9390926103e8565b9290916040519687968c8060a01b03169987610462565b0390a201949294610af4565b80610f105f611a129361031d565b5f6119b9565b80610f105f611a269361031d565b5f610aee565b63bb62587160e01b5f5260045ffd5b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610c3c575f91611a9b575b506001600160a01b0316331415610a85565b611abd915060203d602011611ac3575b611ab5818361031d565b81019061034f565b5f611a89565b503d611aab565b908160011b91808304600214901517156106d257565b90600182018092116106d257565b919082018092116106d257565b611b2c90611b266040516020810190611b1d81610cf684906006602083019252565b51902091611aca565b90611aee565b90611bb5611b3983611ae0565b6040516381e3da6b60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000818116600484015260248301969096527f0000000000000000000000001c0000000000000000000000000000000000000016949092909190602090849081906044820190565b0381885afa928315610c3c575f93611c39575b5082156118b1576040516381e3da6b60e01b81526001600160a01b03929092166004830152602482015292602090849060449082905afa928315610c3c575f93611c15575b509160ff1690565b60ff919350611c329060203d602011610c6f57610c5f818361031d565b9290611c0d565b611c5391935060203d602011610c6f57610c5f818361031d565b915f611bc8565b805191908290602001825e015f815290565b91611cc06001611c9a61036495611cab9560405191602083015260208252611c9560408361031d565b611d21565b926040519485916020830190611c5a565b8260f81b815203601e1981018552018361031d565b60405190602082015260208152611c9560408261031d565b90815160408103611cf457506034602083015160601c92015190565b633fbbeba160e21b5f52600452604060245260445ffd5b6103649392604092825260208201520190611c5a565b5f908051604081115f14611e2d57505f611d4360209260405191828092611c5a565b039060025afa15610c3c5760205f611dbe610cf6611db28351965b6040519283917f363636363636363636363636363636363636363636363636363636363636363689187f36363636363636363636363636363636363636363636363636363636363636368b18898501611d0b565b60405191828092611c5a565b039060025afa15610c3c57611e1d7f5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c611db25f93610cf66020968651908560405196879518911889850191606093918352602083015260408201520190565b039060025afa15610c3c575f5190565b6020808301519490821193509160018414611e9c57505f925b60208210611e86575b6040821016611e6c575b505f611dbe610cf6611db2602094611d5e565b600160409190910360031b1b5f190119909116905f611e59565b935f1960018360200360031b1b01191693611e4f565b6040015192611e4656fea26469706673582212205f594d0b1787c58d3740e820b1a834d2ed0d3537203397452ab66522902123e164736f6c63430008210033" + }, + "0x1c00000000000000000000000000000000000002": { + "nonce": "0x1", + "balance": "0x0", + "code": "0x60806040526004361015610011575f80fd5b5f3560e01c80632c37826e14610144578063340652721461013f578063378fa8fa1461013a57806343c3cb831461013557806348aa41081461013057806353a8d7391461012b578063545525f11461012657806379502c551461012157806379fa32891461011c5780637b9c9aa414610117578063a94cd93114610112578063b3b200aa1461010d578063b79a6c0c14610108578063bba9282e14610103578063c9b6ca9b146100fe578063ce7025e9146100f9578063d93af1d2146100f4578063e2e3ee5c146100ef5763f490ca96146100ea575f80fd5b610917565b6107cd565b6107ab565b610732565b610716565b6106ee565b610610565b610578565b6104e6565b610468565b6102ea565b610264565b610247565b61022b565b6101d1565b6101b6565b61019b565b610176565b610157565b5f91031261015357565b5f80fd5b34610153575f3660031901126101535760205f5460c01c604051908152f35b34610153575f3660031901126101535760206001600160801b035f5416604051908152f35b34610153575f36600319011261015357602060405160218152f35b34610153575f36600319011261015357602060405160718152f35b34610153575f366003190112610153575f60206040516101f08161094d565b8281520152604080516102028161094d565b6001600160401b0360015491828152602082600254169101908152835192835251166020820152f35b34610153575f3660031901126101535760206040516104008152f35b34610153575f366003190112610153576020600554604051908152f35b34610153575f366003190112610153576040517f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03168152602090f35b600435906001600160801b038216820361015357565b604435906001600160801b038216820361015357565b602435906001600160801b038216820361015357565b34610153576020366003190112610153576103036102a8565b331515806103a8575b61039957670de0b6b3a76400006001600160801b0382161161038a576103858161036b7f6f864cce5237e12ffc9a99fc6c59af17222c2bbb3457690cc8753ab16b5d715e936001600160801b03166001600160801b03195f5416175f55565b6040516001600160801b0390911681529081906020820190565b0390a1005b630d62f21160e11b5f5260045ffd5b63bb62587160e01b5f5260045ffd5b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610437575f91610408575b506001600160a01b031633141561030c565b61042a915060203d602011610430575b610422818361096d565b8101906109bf565b5f6103f6565b503d610418565b6109d7565b608435906001600160401b038216820361015357565b602435906001600160401b038216820361015357565b34610153576020366003190112610153576004356001600160401b038116810361015357610497602091610a19565b6001600160801b0360405191168152f35b6001600160a01b0381160361015357565b9181601f84011215610153578235916001600160401b038311610153576020838186019501011161015357565b346101535760e036600319011261015357600435610503816104a8565b60243590610510826104a8565b6105186102be565b9160643561052461043c565b60a43591610531836104a8565b60c435956001600160401b0387116101535761055e6105576105769836906004016104b9565b3691610a79565b946040519661056e60208961096d565b5f8852611036565b005b346101535761010036600319011261015357600435610596816104a8565b6024356105a2816104a8565b6105aa6102be565b916064356105b661043c565b9060a4356105c3816104a8565b60c4356001600160401b038111610153576105e29036906004016104b9565b93909260e435976001600160401b038911610153576106086105769936906004016104b9565b989097610ac3565b34610153576020366003190112610153576004353315158061066f575b610399576103858161065f7f4f0c4dec68e1e774843a5fc3a522ab2a832ecfc975b9ad8a5033736d9e47f09d93600555565b6040519081529081906020820190565b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610437575f916106cf575b506001600160a01b031633141561062d565b6106e8915060203d60201161043057610422818361096d565b5f6106bd565b34610153575f3660031901126101535760206001600160401b035f5460801c16604051908152f35b34610153575f36600319011261015357602060405161c3508152f35b346101535760603660031901126101535760043561074e610452565b604435916001600160401b0383116101535736602384011215610153578260040135916001600160401b038311610153573660248460051b86010111610153576107a161065f9360246107a79601610aea565b9161170b565b0390f35b34610153575f3660031901126101535760206107c5610b87565b604051908152f35b34610153576060366003190112610153576004356107ea816104a8565b6107f26102d4565b906044356107ff816104a8565b33151580610898575b610399576105769261084e61085e9261083161082261098e565b6001600160a01b039096168652565b5f6020860181905260408601526001600160a01b03166060850152565b6001600160801b03166080830152565b5f60a08201525f60c08201525f60e08201525f61010082015261087f610aaf565b61012082015261088d610aaf565b610140820152610d74565b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610437575f916108f8575b506001600160a01b0316331415610808565b610911915060203d60201161043057610422818361096d565b5f6108e6565b34610153575f366003190112610153576020604051670de0b6b3a76400008152f35b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b0382111761096857604052565b610939565b90601f801991011681019081106001600160401b0382111761096857604052565b6040519061099e6101608361096d565b565b6040519061099e6101408361096d565b6040519061099e60408361096d565b9081602091031261015357516109d4816104a8565b90565b6040513d5f823e3d90fd5b634e487b7160e01b5f52601160045260245ffd5b6001600160401b036001911601906001600160401b038211610a1457565b6109e2565b6001600160401b031661c350016001600160401b038111610a14576001600160401b036001600160801b035f54169116026001600160801b038116908103610a145790565b6001600160401b03811161096857601f01601f191660200190565b929192610a8582610a5e565b91610a93604051938461096d565b829481845281830111610153578281602093845f960137010152565b60405190610abe60208361096d565b5f8252565b97610adc610ae492939495969761099e9b993691610a79565b973691610a79565b96611036565b6001600160401b038211610968578160051b9060405192610b0e602084018561096d565b835260208301918101903682116101535780925b828410610b30575050505090565b83356001600160401b03811161015357820136601f8201121561015357602091610b61839236908481359101610a79565b815201930192610b22565b5f19810191908211610a1457565b91908203918211610a1457565b6004546003549081811015610ba2578103908111610a145790565b50505f90565b634e487b7160e01b5f52603260045260245ffd5b600354811015610bd85760035f52600960205f20910201905f90565b610ba8565b8054821015610bd8575f52600960205f20910201905f90565b634e487b7160e01b5f525f60045260245ffd5b90600182811c92168015610c37575b6020831014610c2357565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610c18565b5f5b828110610c4f57505050565b5f82820155600101610c43565b91601f8211610c6a57505050565b808211610c7657505050565b61099e925f5260205f20916020601f830160051c9210610ca1575b601f82910160051c039101610c41565b5f9150610c91565b91909182516001600160401b03811161096857610cd081610cca8454610c09565b84610c5c565b6020601f8211600114610d0f578190610d009394955f92610d04575b50508160011b915f199060031b1c19161790565b9055565b015190505f80610cec565b601f19821690610d22845f5260205f2090565b915f5b818110610d5c57509583600195969710610d44575b505050811b019055565b01515f1960f88460031b161c191690555f8080610d3a565b9192602060018192868b015181550194019201610d25565b6003546801000000000000000081101561096857806001610d9a92016003556003610bdd565b610f2257815181546001600160a01b0319166001600160a01b0390911617815561099e916008906101409060208101516001850180546001600160a01b0319166001600160a01b039092169190911790556040810151600285015560608101516003850180546001600160a01b0319166001600160a01b03909216919091179055610e8360048501610e55610e3960808501516001600160801b031690565b82546001600160801b0319166001600160801b03909116178255565b60a08301516001600160801b031681546001600160801b031660809190911b6001600160801b031916179055565b60c08101516005850155610f0760068501610ec8610eab60e08501516001600160401b031690565b825467ffffffffffffffff19166001600160401b03909116178255565b6101008301516001600160a01b0316815468010000000000000000600160e01b03191660409190911b68010000000000000000600160e01b0316179055565b610f1961012082015160078601610ca9565b01519101610ca9565b610bf6565b5f198114610a145760010190565b906001600160801b03809116911601906001600160801b038211610a1457565b90816020910312610153575190565b90816020910312610153575180151581036101535790565b6001600160401b03166001600160401b038114610a145760010190565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b6001600160a01b03918216815291811660208301526001600160801b03928316604083015292909116606082015260808101929092526001600160401b039290921660a0820152911660c082015261012060e082018190526109d493919261102791840190610f99565b91610100818403910152610f99565b95969092949693919360018060a01b03881615611350576104008151116113415761106082611ac0565b6005546112ee575b61107183610a19565b9761107c8987610f35565b60405163868a2e9d60e01b8152979094906020896004815f60056007609a1b015af1988915610437575f996112bd575b5088156112ae576040516323b872dd60e01b81523360048201523060248201526001600160801b03871660448201526001600160a01b038b16906020816064815f865af1908115610437575f9161127f575b501561127057803b1561015357604051630852cd8d60e31b81526001600160801b039790971660048801525f908790602490829084905af18015610437577f348c28d1410ff29393c038fe0f1998384082e98e315624b24c04a4fa6288b9de99611251976111f292611256575b5061117461098e565b6001600160a01b038d1681529033602083015260408201526001600160a01b03891660608201526001600160801b038a1660808201526001600160801b038d1660a082015260c081018390526001600160401b03841660e08201526001600160a01b0385166101008201528561012082015286610140820152610d74565b5f5460801c6001600160401b03169a61123961120d8d610f7c565b5f805467ffffffffffffffff60801b191660809290921b67ffffffffffffffff60801b16919091179055565b6040519889986001600160401b03339e169c8a610fbd565b0390a3565b806112645f61126a9361096d565b80610149565b5f61116b565b6312171d8360e31b5f5260045ffd5b6112a1915060203d6020116112a7575b611299818361096d565b810190610f64565b5f6110fe565b503d61128f565b632968ee7f60e21b5f5260045ffd5b6112e091995060203d6020116112e7575b6112d8818361096d565b810190610f55565b975f6110ac565b503d6112ce565b600754430361132a575b60065460055481101561131b5761131161131691610f27565b600655565b611068565b63124ab48560e11b5f5260045ffd5b61133343600755565b61133c5f600655565b6112f8565b634b8a874d60e11b5f5260045ffd5b63c29f0c7160e01b5f5260045ffd5b91908201809211610a1457565b9060405191825f82549261137f84610c09565b80845293600181169081156113e857506001146113a4575b5061099e9250038361096d565b90505f9291925260205f20905f915b8183106113cc57505090602061099e928201015f611397565b60209193508060019154838589010152019101909184926113b3565b90506020925061099e94915060ff191682840152151560051b8201015f611397565b9061150a600861141861098e565b84546001600160a01b031681529360018101546001600160a01b031660208601526002810154604086015260038101546001600160a01b0316606086015261149a61148a6004830154611484611474826001600160801b031690565b6001600160801b031660808a0152565b60801c90565b6001600160801b031660a0870152565b600581015460c08601526114f26114e160068301546114d26114c2826001600160401b031690565b6001600160401b031660e08a0152565b60401c6001600160a01b031690565b6001600160a01b0316610100870152565b6114fe6007820161136c565b6101208601520161136c565b610140830152565b8051821015610bd85760209160051b010190565b604080825282516001600160a01b0316908201529291906020906115eb9080830151606087015260408101516001600160a01b0316608087015260608101516001600160801b031660a087015260808101516001600160801b031660c087015260a081015160e087015260c08101516001600160401b031661010087015260e08101516001600160a01b03166101208701526101206115d6610100830151610140808a0152610180890190610f99565b910151868203603f1901610160880152610f99565b930152565b6115fa8154610c09565b9081611604575050565b81601f5f9311600114611615575055565b8183526020832061163291601f0160051c84190190600101610c41565b808252602082209081548360011b9084198560031b1c191617905555565b90610f22576008815f61099e93555f60018201555f60028201555f60038201555f60048201555f60058201555f600682015561168e600782016115f0565b016115f0565b6003545f600355806116a35750565b80600902906009820403610a145760035f5260205f205f5b8281106116c757505050565b80611705600860099385015f81555f60018201555f60028201555f60038201555f60048201555f60058201555f600682015561168e600782016115f0565b016116bb565b9092915f9333151580611a41575b610399576001600160401b03804316911603611a3257600354906117406004548093610b7a565b808411611a2a575b508051838103611a13575082611820575b50505061179661177261176d5f5460c01c90565b6109f6565b5f80546001600160c01b031660c09290921b6001600160c01b031916919091179055565b817fec4aff46c65f485f4b15e3c2edadda1d57d002995f5aa262a27c76b9a680ec1661181b6117c65f5460c01c90565b6118016117d16109b0565b8581526001600160401b038316602090910181905260018690556002805467ffffffffffffffff19169091179055565b6040516001600160401b0390911681529081906020820190565b0390a2565b5f1994509161182f908261135f565b91825b8281116118695750505060045560045460035414611853575b5f8080611759565b61185b611694565b6118645f600455565b61184b565b61187281610b6c565b9561187c87610bbc565b506118869061140a565b6118908589610b7a565b61189a9085611512565b5180610140830151906118ac91611b35565b8151602080840151604080860151905160609290921b6bffffffffffffffffffffffff191692820192835260348083019190915281526001600160a01b0390921693916118fa60548261096d565b51902060608201519091906001600160a01b031660808201516001600160801b031660a08301516001600160801b031660c08401519160e0850151611945906001600160401b031690565b6101008601519094906001600160a01b0316956101200151966119666109a0565b6001600160a01b03909a168a5260208a01526001600160a01b031660408901526001600160801b031660608801526001600160801b0316608087015260a08601526001600160401b031660c08501526001600160a01b031660e0840152610100830152610120820152604051809160208201936119e39185611526565b03601f19810182526119f5908261096d565b51902095611a0290610bbc565b611a0b91611650565b5f1901611832565b630db2128560e11b5f52600452602483905260445ffd5b92505f611748565b631391e11b60e21b5f5260045ffd5b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610437575f91611aa1575b506001600160a01b0316331415611719565b611aba915060203d60201161043057610422818361096d565b5f611a8f565b80518015611b3157602103611b1357805115610bd85760208101516001600160f81b031916600160f91b8114159081611b22575b50611b1357611b096021611b0d920151611bb7565b1590565b611b1357565b6361d0136b60e11b5f5260045ffd5b600360f81b141590505f611af4565b5050565b51611b5e575f905b51818103611b49575050565b63521a2d4d60e11b5f5260045260245260445ffd5b607190611b3d565b3d15611b90573d90611b7782610a5e565b91611b85604051938461096d565b82523d5f602084013e565b606090565b602081519101519060208110611ba9575090565b5f199060200360031b1b1690565b80158015611c75575b611c64575f8091604051611c3a81611c2c602082019460076401000003d019916401000003d019906401000003d019818009090860208087528087018190526040870152606086015263800001e9600160ff1b0360808601526401000003d01960a086015260c0850190565b03601f19810183528261096d565b519060055afa611c48611b66565b90158015611c69575b611c6457611c60600191611b95565b1490565b505f90565b50602081511415611c51565b506401000003d019811015611bc056fea26469706673582212201e990a2f2419ab12382903e485798553edca5df5037cb6c857af92e834e72f3f64736f6c63430008210033" + }, + "0x1c00000000000000000000000000000000000003": { + "nonce": "0x1", + "balance": "0x0", + "code": "0x6080806040526004361015610012575f80fd5b5f3560e01c9081631beb1ab814610561575080631fbb25ad1461051d5780633488ce0d146102dd5780635c1bba381461023b5780636d46e98714610193578063a21de6d91461014f5763e202d99514610069575f80fd5b34610138575f366003190112610138576040516381e3da6b60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260016024830152602090829060449082907f0000000000000000000000001c00000000000000000000000000000000000000165afa8015610144575f9061010d575b6040516001600160a01b039091168152602090f35b506020813d60201161013c575b816101276020938361067c565b8101031261013857602090516100f8565b5f80fd5b3d915061011a565b6040513d5f823e3d90fd5b34610138575f366003190112610138576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610138576020366003190112610138576004356001600160a01b0381169081900361013857604051630b83774760e31b8152602081600481305afa908115610144575f916101f6575b506040516001600160a01b039091169091148152602090f35b90506020813d602011610233575b816102116020938361067c565b810103126101385751906001600160a01b0382168203610138579060206101dd565b3d9150610204565b34610138575f366003190112610138576040516381e3da6b60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301525f6024830152602090829060449082907f0000000000000000000000001c00000000000000000000000000000000000000165afa8015610144575f9061010d576040516001600160a01b039091168152602090f35b34610138575f366003190112610138576040516381e3da6b60e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b038181166004840152600660248401527f0000000000000000000000001c00000000000000000000000000000000000000169190602082604481865afa918215610144575f926104e9575b5081156104da576040516020810190600682526020815261038f60408261067c565b519020915f1981019081116104c6578060011b90808204600214901517156104c65782018092116104c65760018201908183116104c6576040516381e3da6b60e01b81526001600160a01b03821660048201526024810193909352602083604481875afa928315610144575f9361048e575b506040516381e3da6b60e01b81526001600160a01b03909116600482015260248101919091529160209083908180604481015b03915afa918215610144575f92610459575b5060ff6040928351928352166020820152f35b91506020823d602011610486575b816104746020938361067c565b810103126101385790519060ff610446565b3d9150610467565b919092506020823d6020116104be575b816104ab6020938361067c565b8101031261013857905191610434610401565b3d915061049e565b634e487b7160e01b5f52601160045260245ffd5b630c322fb560e31b5f5260045ffd5b9091506020813d602011610515575b816105056020938361067c565b810103126101385751908361036d565b3d91506104f8565b34610138575f366003190112610138576040517f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b03168152602090f35b34610138576020366003190112610138576004356001600160a01b0381169190829003610138576105fe9181602080930191825260076040820152604081526105ab60608261067c565b5190206040516381e3da6b60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166004820152602481019190915291829081906044820190565b03817f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b03165afa8015610144575f90610649575b60209060ff604051911615158152f35b506020813d602011610674575b816106636020938361067c565b810103126101385760209051610639565b3d9150610656565b90601f8019910116810190811067ffffffffffffffff82111761069e57604052565b634e487b7160e01b5f52604160045260245ffdfea2646970667358221220fea47fd4d17ab5457f7b15375f57343e40c861f7e510dd86233cf1280fe3069d64736f6c63430008210033" + }, + "0x1c00000000000000000000000000000000000004": { + "nonce": "0x1", + "balance": "0x0", + "code": "0xfe" + }, + "0x20c0000000000000000000000000000000000000": { + "nonce": "0x0", + "balance": "0x0", + "code": "0xef", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x706174685553440000000000000000000000000000000000000000000000000e", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x706174685553440000000000000000000000000000000000000000000000000e", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5553440000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000010000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000000000000000000000000000000000000000000d": "0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff", + "0x1a08d1eefb6dea6eba7c6c1f53fa17f31dc24b9efe98e97550f0dad434642618": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x353fe882519f79b8caf8d301c26c19d663ae2e691ca2e75dc341b346d5d22c63": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x983ee3ed0ac6ffe1e6626c807d5dad57db7645721c041f19b39c3f728acefdd7": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x9a3d8dc9bf2bb7465d975ea80af65f820bc69e3b43668ac11765d4e28cf9333a": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xad6e221fb67208b50def8b13e82392da7f9eaacd7b17f77c8bfdc7df401bc3d8": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0xbd1422d956203483f6a77a55f068041e264cef0ec8c355db258a1fb8f4169a51": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xc39d774f18115b85b81494d65e588b565d73abc969333d1da7b0a0eb0729accd": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + } + }, + "0x20fc000000000000000000000000000000000000": { + "nonce": "0x0", + "balance": "0x0", + "code": "0xef" + }, + "0x403c000000000000000000000000000000000000": { + "nonce": "0x0", + "balance": "0x0", + "code": "0xef" + }, + "0x4e4f4e4345000000000000000000000000000000": { + "nonce": "0x0", + "balance": "0x0", + "code": "0xef" + }, + "0xaaaaaaaa00000000000000000000000000000000": { + "nonce": "0x0", + "balance": "0x0", + "code": "0xef" + }, + "0xca11bde05977b3631167028862be2a173976ca11": { + "nonce": "0x1", + "balance": "0x0", + "code": "0x6080604052600436106100f35760003560e01c80634d2301cc1161008a578063a8b0574e11610059578063a8b0574e1461025a578063bce38bd714610275578063c3077fa914610288578063ee82ac5e1461029b57600080fd5b80634d2301cc146101ec57806372425d9d1461022157806382ad56cb1461023457806386d516e81461024757600080fd5b80633408e470116100c65780633408e47014610191578063399542e9146101a45780633e64a696146101c657806342cbb15c146101d957600080fd5b80630f28c97d146100f8578063174dea711461011a578063252dba421461013a57806327e86d6e1461015b575b600080fd5b34801561010457600080fd5b50425b6040519081526020015b60405180910390f35b61012d610128366004610a85565b6102ba565b6040516101119190610bbe565b61014d610148366004610a85565b6104ef565b604051610111929190610bd8565b34801561016757600080fd5b50437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0140610107565b34801561019d57600080fd5b5046610107565b6101b76101b2366004610c60565b610690565b60405161011193929190610cba565b3480156101d257600080fd5b5048610107565b3480156101e557600080fd5b5043610107565b3480156101f857600080fd5b50610107610207366004610ce2565b73ffffffffffffffffffffffffffffffffffffffff163190565b34801561022d57600080fd5b5044610107565b61012d610242366004610a85565b6106ab565b34801561025357600080fd5b5045610107565b34801561026657600080fd5b50604051418152602001610111565b61012d610283366004610c60565b61085a565b6101b7610296366004610a85565b610a1a565b3480156102a757600080fd5b506101076102b6366004610d18565b4090565b60606000828067ffffffffffffffff8111156102d8576102d8610d31565b60405190808252806020026020018201604052801561031e57816020015b6040805180820190915260008152606060208201528152602001906001900390816102f65790505b5092503660005b8281101561047757600085828151811061034157610341610d60565b6020026020010151905087878381811061035d5761035d610d60565b905060200281019061036f9190610d8f565b6040810135958601959093506103886020850185610ce2565b73ffffffffffffffffffffffffffffffffffffffff16816103ac6060870187610dcd565b6040516103ba929190610e32565b60006040518083038185875af1925050503d80600081146103f7576040519150601f19603f3d011682016040523d82523d6000602084013e6103fc565b606091505b50602080850191909152901515808452908501351761046d577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260846000fd5b5050600101610325565b508234146104e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d756c746963616c6c333a2076616c7565206d69736d6174636800000000000060448201526064015b60405180910390fd5b50505092915050565b436060828067ffffffffffffffff81111561050c5761050c610d31565b60405190808252806020026020018201604052801561053f57816020015b606081526020019060019003908161052a5790505b5091503660005b8281101561068657600087878381811061056257610562610d60565b90506020028101906105749190610e42565b92506105836020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166105a66020850185610dcd565b6040516105b4929190610e32565b6000604051808303816000865af19150503d80600081146105f1576040519150601f19603f3d011682016040523d82523d6000602084013e6105f6565b606091505b5086848151811061060957610609610d60565b602090810291909101015290508061067d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b50600101610546565b5050509250929050565b43804060606106a086868661085a565b905093509350939050565b6060818067ffffffffffffffff8111156106c7576106c7610d31565b60405190808252806020026020018201604052801561070d57816020015b6040805180820190915260008152606060208201528152602001906001900390816106e55790505b5091503660005b828110156104e657600084828151811061073057610730610d60565b6020026020010151905086868381811061074c5761074c610d60565b905060200281019061075e9190610e76565b925061076d6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166107906040850185610dcd565b60405161079e929190610e32565b6000604051808303816000865af19150503d80600081146107db576040519150601f19603f3d011682016040523d82523d6000602084013e6107e0565b606091505b506020808401919091529015158083529084013517610851577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260646000fd5b50600101610714565b6060818067ffffffffffffffff81111561087657610876610d31565b6040519080825280602002602001820160405280156108bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816108945790505b5091503660005b82811015610a105760008482815181106108df576108df610d60565b602002602001015190508686838181106108fb576108fb610d60565b905060200281019061090d9190610e42565b925061091c6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff1661093f6020850185610dcd565b60405161094d929190610e32565b6000604051808303816000865af19150503d806000811461098a576040519150601f19603f3d011682016040523d82523d6000602084013e61098f565b606091505b506020830152151581528715610a07578051610a07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b506001016108c3565b5050509392505050565b6000806060610a2b60018686610690565b919790965090945092505050565b60008083601f840112610a4b57600080fd5b50813567ffffffffffffffff811115610a6357600080fd5b6020830191508360208260051b8501011115610a7e57600080fd5b9250929050565b60008060208385031215610a9857600080fd5b823567ffffffffffffffff811115610aaf57600080fd5b610abb85828601610a39565b90969095509350505050565b6000815180845260005b81811015610aed57602081850181015186830182015201610ad1565b81811115610aff576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b84811015610bb1578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051151584528401516040858501819052610b9d81860183610ac7565b9a86019a9450505090830190600101610b4f565b5090979650505050505050565b602081526000610bd16020830184610b32565b9392505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610c52577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610c40868351610ac7565b95509284019290840190600101610c06565b509398975050505050505050565b600080600060408486031215610c7557600080fd5b83358015158114610c8557600080fd5b9250602084013567ffffffffffffffff811115610ca157600080fd5b610cad86828701610a39565b9497909650939450505050565b838152826020820152606060408201526000610cd96060830184610b32565b95945050505050565b600060208284031215610cf457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610bd157600080fd5b600060208284031215610d2a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112610dc357600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610e0257600080fd5b83018035915067ffffffffffffffff821115610e1d57600080fd5b602001915036819003821315610a7e57600080fd5b8183823760009101908152919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610dc357600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112610dc357600080fdfea2646970667358221220bb2b5c71a328032f97c676ae39a1ec2148d3e5d6f73d95e9b17910152d61f16264736f6c634300080c0033" + }, + "0xdec0000000000000000000000000000000000000": { + "nonce": "0x0", + "balance": "0x0", + "code": "0xef" + }, + "0xfeec000000000000000000000000000000000000": { + "nonce": "0x0", + "balance": "0x0", + "code": "0xef", + "storage": { + "0xabd7b398c2237712843e3e780dcd40dfb99446b30666f04c025da4efa5ce5177": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + } + }, + "baseFeePerGas": "0x2540be400" +} \ No newline at end of file diff --git a/crates/tempo-zone/tests/it/deposit.rs b/crates/tempo-zone/tests/it/deposit.rs index cd4fbb4be..4aae4c001 100644 --- a/crates/tempo-zone/tests/it/deposit.rs +++ b/crates/tempo-zone/tests/it/deposit.rs @@ -123,7 +123,13 @@ async fn test_l1_deposit_mints_on_zone() -> eyre::Result<()> { // Execute deposit on L1 let deposit_receipt = portal - .deposit(l1_token_address, recipient, deposit_amount, B256::ZERO, Address::ZERO) + .deposit( + l1_token_address, + recipient, + deposit_amount, + B256::ZERO, + Address::ZERO, + ) .send() .await? .get_receipt() diff --git a/crates/tempo-zone/tests/it/l1_e2e.rs b/crates/tempo-zone/tests/it/l1_e2e.rs index 33e5ae255..4fb502852 100644 --- a/crates/tempo-zone/tests/it/l1_e2e.rs +++ b/crates/tempo-zone/tests/it/l1_e2e.rs @@ -1250,7 +1250,13 @@ async fn test_blacklisted_sender_transfer_rejected() -> eyre::Result<()> { let portal = ZonePortal::new(portal_address, &dev_provider); let receipt = portal - .deposit(PATH_USD_ADDRESS, alice, deposit_amount, B256::ZERO, Address::ZERO) + .deposit( + PATH_USD_ADDRESS, + alice, + deposit_amount, + B256::ZERO, + Address::ZERO, + ) .send() .await? .get_receipt() diff --git a/crates/tempo-zone/tests/it/utils.rs b/crates/tempo-zone/tests/it/utils.rs index 9f68a88bb..85fb2e77c 100644 --- a/crates/tempo-zone/tests/it/utils.rs +++ b/crates/tempo-zone/tests/it/utils.rs @@ -1931,7 +1931,13 @@ impl ZoneAccount { let portal = ZonePortal::new(self.portal_address, &self.l1_provider); let receipt = portal - .deposit(PATH_USD_ADDRESS, recipient, amount, B256::ZERO, Address::ZERO) + .deposit( + PATH_USD_ADDRESS, + recipient, + amount, + B256::ZERO, + Address::ZERO, + ) .send() .await? .get_receipt() @@ -1986,7 +1992,13 @@ impl ZoneAccount { let portal = ZonePortal::new(self.portal_address, &self.l1_provider); let receipt = portal - .deposit(token, self.address, amount, B256::ZERO, Address::ZERO) + .deposit( + token, + self.address, + amount, + B256::ZERO, + Address::ZERO, + ) .send() .await? .get_receipt() diff --git a/xtask/src/demo_blacklist.rs b/xtask/src/demo_blacklist.rs index 410c42170..e89e45c65 100644 --- a/xtask/src/demo_blacklist.rs +++ b/xtask/src/demo_blacklist.rs @@ -329,7 +329,13 @@ impl DemoBlacklist { let mut pending = None; for attempt in 0..5u32 { match portal - .deposit(token_addr, admin, deposit_amount, B256::ZERO, Address::ZERO) + .deposit( + token_addr, + admin, + deposit_amount, + B256::ZERO, + Address::ZERO, + ) .send() .await { @@ -467,7 +473,13 @@ impl DemoBlacklist { let gas_fund: u128 = 100_000; let l2_block_before = l2.get_block_number().await.unwrap_or(0); let receipt = portal - .deposit(PATH_USD_ADDRESS, target, gas_fund, B256::ZERO, Address::ZERO) + .deposit( + PATH_USD_ADDRESS, + target, + gas_fund, + B256::ZERO, + Address::ZERO, + ) .send_sync() .await?; check(&receipt, "deposit pathUSD to target for gas")?; diff --git a/xtask/src/demo_swap_and_deposit.rs b/xtask/src/demo_swap_and_deposit.rs index e36c073a4..fe17082e1 100644 --- a/xtask/src/demo_swap_and_deposit.rs +++ b/xtask/src/demo_swap_and_deposit.rs @@ -280,7 +280,13 @@ impl DemoSwapAndDeposit { .await .wrap_err("failed to approve AlphaUSD for portal")?; let receipt = portal_contract - .deposit(alpha, operator, alpha_gross_deposit, B256::ZERO, Address::ZERO) + .deposit( + alpha, + operator, + alpha_gross_deposit, + B256::ZERO, + Address::ZERO, + ) .send_sync() .await .wrap_err("failed to deposit AlphaUSD to the zone")?; diff --git a/xtask/src/generate_zone_genesis.rs b/xtask/src/generate_zone_genesis.rs index 742fdae2f..c885cb09b 100644 --- a/xtask/src/generate_zone_genesis.rs +++ b/xtask/src/generate_zone_genesis.rs @@ -162,8 +162,13 @@ impl GenerateZoneGenesis { nonce += 1; let zone_inbox_bytecode = load_artifact(&self.specs_out, "ZoneInbox")?; - let zone_inbox_args = - (ZONE_CONFIG_ADDRESS, self.tempo_portal, TEMPO_STATE_ADDRESS).abi_encode_params(); + let zone_inbox_args = ( + ZONE_CONFIG_ADDRESS, + self.tempo_portal, + TEMPO_STATE_ADDRESS, + ZONE_OUTBOX_ADDRESS, + ) + .abi_encode_params(); deploy_contract( &mut evm, &zone_inbox_bytecode, From e9e3d2897e398b47eca97f18c9edaf2aed52d975 Mon Sep 17 00:00:00 2001 From: Derek Cofausper <256792747+decofe@users.noreply.github.com> Date: Mon, 6 Apr 2026 04:53:11 +0000 Subject: [PATCH 04/12] fix: cargo fmt Co-Authored-By: dankrad <6130607+dankrad@users.noreply.github.com> Amp-Thread-ID: https://ampcode.com/threads/T-019d5f52-e187-7554-b95f-59c7b789eb28 --- crates/tempo-zone/tests/it/utils.rs | 8 +------- xtask/src/demo_blacklist.rs | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/crates/tempo-zone/tests/it/utils.rs b/crates/tempo-zone/tests/it/utils.rs index 85fb2e77c..1fba8dcfe 100644 --- a/crates/tempo-zone/tests/it/utils.rs +++ b/crates/tempo-zone/tests/it/utils.rs @@ -1992,13 +1992,7 @@ impl ZoneAccount { let portal = ZonePortal::new(self.portal_address, &self.l1_provider); let receipt = portal - .deposit( - token, - self.address, - amount, - B256::ZERO, - Address::ZERO, - ) + .deposit(token, self.address, amount, B256::ZERO, Address::ZERO) .send() .await? .get_receipt() diff --git a/xtask/src/demo_blacklist.rs b/xtask/src/demo_blacklist.rs index e89e45c65..aa0a97ab2 100644 --- a/xtask/src/demo_blacklist.rs +++ b/xtask/src/demo_blacklist.rs @@ -329,13 +329,7 @@ impl DemoBlacklist { let mut pending = None; for attempt in 0..5u32 { match portal - .deposit( - token_addr, - admin, - deposit_amount, - B256::ZERO, - Address::ZERO, - ) + .deposit(token_addr, admin, deposit_amount, B256::ZERO, Address::ZERO) .send() .await { From 381b3317fb5d82424b6193258b166a6e3f51a55b Mon Sep 17 00:00:00 2001 From: Derek Cofausper <256792747+decofe@users.noreply.github.com> Date: Mon, 6 Apr 2026 05:59:11 +0000 Subject: [PATCH 05/12] fix: restore unscoped auth tokens, validity window, and TIP-403 behavior Reverts unrelated changes that were bundled with the deposit bounceback PR: - Restore zone_id=0 unscoped token support in auth validation - Restore 30-day (2592000s) max validity window (was changed to 30min) - Restore enforce_transfer rejecting on policy resolution failure - Restore enforce_mint doc comment about L1 enforcement deferral - Restore MockPolicyProvider::failing() test helper - Restore policy cache seeding in start_local_zone_with_fixture Co-authored-by: dankrad <6130607+dankrad@users.noreply.github.com> Amp-Thread-ID: https://ampcode.com/threads/T-019d5f52-e187-7554-b95f-59c7b789eb28 --- crates/precompiles/src/ztip20.rs | 26 ++++++++++++++----- crates/rpc/src/auth/token.rs | 10 ++++--- crates/rpc/src/error.rs | 2 +- crates/rpc/src/provider.rs | 2 +- crates/tempo-zone/tests/it/private_rpc_e2e.rs | 2 +- crates/tempo-zone/tests/it/utils.rs | 8 ++++++ 6 files changed, 38 insertions(+), 12 deletions(-) diff --git a/crates/precompiles/src/ztip20.rs b/crates/precompiles/src/ztip20.rs index e57387e2b..673e6f625 100644 --- a/crates/precompiles/src/ztip20.rs +++ b/crates/precompiles/src/ztip20.rs @@ -21,7 +21,7 @@ use tempo_precompiles::{ storage::{StorageCtx, evm::EvmPrecompileStorageProvider}, tip20::{IRolesAuth, ITIP20, RolesAuthError, TIP20Token}, }; -use tracing::{debug, trace}; +use tracing::{trace, warn}; use zone_primitives::{ abi::Unauthorized, constants::{ZONE_INBOX_ADDRESS, ZONE_OUTBOX_ADDRESS}, @@ -217,12 +217,12 @@ impl ZoneTip20Token

{ let policy_id = match Self::resolve_transfer_policy_id(registry, token) { Ok(id) => id, Err(e) => { - debug!( + warn!( target: "zone::precompile", %token, error = %e, - "failed to resolve transfer_policy_id, deferring to vanilla TIP20" + "failed to resolve transfer_policy_id, rejecting transfer" ); - return None; + return Some(Err(e)); } }; @@ -248,15 +248,17 @@ impl ZoneTip20Token

{ /// Check mint recipient authorization. /// /// Returns `Some(revert)` if forbidden, `None` if allowed. + /// Resolution errors are treated as allow because mints are triggered by + /// deposit system transactions whose policy is already enforced on L1. fn enforce_mint(&self, token: Address, to: Address) -> Option { let registry = self.registry.as_ref()?; let policy_id = match Self::resolve_transfer_policy_id(registry, token) { Ok(id) => id, Err(e) => { - debug!( + warn!( target: "zone::precompile", %token, error = %e, - "failed to resolve transfer_policy_id, deferring to vanilla TIP20" + "failed to resolve transfer_policy_id for mint, deferring to L1 enforcement" ); return None; } @@ -436,6 +438,7 @@ mod tests { transfer_authorized: bool, mint_authorized: bool, policy_id: u64, + fail_policy_id_resolution: bool, } impl MockPolicyProvider { @@ -444,6 +447,14 @@ mod tests { transfer_authorized: true, mint_authorized: true, policy_id: 1, + fail_policy_id_resolution: false, + } + } + + fn failing() -> Self { + Self { + fail_policy_id_resolution: true, + ..Default::default() } } } @@ -463,6 +474,9 @@ mod tests { } fn resolve_transfer_policy_id(&self, _token: Address) -> Result { + if self.fail_policy_id_resolution { + return Err(PrecompileError::other("RPC unavailable")); + } Ok(self.policy_id) } diff --git a/crates/rpc/src/auth/token.rs b/crates/rpc/src/auth/token.rs index 7d4a0b7df..f0003453a 100644 --- a/crates/rpc/src/auth/token.rs +++ b/crates/rpc/src/auth/token.rs @@ -43,7 +43,7 @@ pub struct AuthContext { pub struct AuthorizationToken { /// Spec version (must be 0). pub version: u8, - /// Zone ID. + /// Zone ID (0 = unscoped, valid for any zone). pub zone_id: u32, /// Chain ID. pub chain_id: u64, @@ -104,6 +104,8 @@ impl AuthorizationToken { } /// Validate token fields against the server's zone configuration. + /// + /// A `zone_id` of `0` is unscoped and accepted for any zone. pub fn validate( &self, expected_zone_id: u32, @@ -113,7 +115,7 @@ impl AuthorizationToken { if self.version != 0 { return Err(AuthError::UnsupportedVersion(self.version)); } - if self.zone_id != expected_zone_id { + if self.zone_id != 0 && self.zone_id != expected_zone_id { return Err(AuthError::ZoneIdMismatch); } if self.chain_id != expected_chain_id { @@ -122,7 +124,7 @@ impl AuthorizationToken { if self.zone_portal != expected_portal { return Err(AuthError::ZonePortalMismatch); } - if self.expires_at.saturating_sub(self.issued_at) > 1800 { + if self.expires_at.saturating_sub(self.issued_at) > 2_592_000 { return Err(AuthError::WindowTooLarge); } @@ -146,6 +148,8 @@ impl AuthorizationToken { /// /// Returns `(fields, digest)` where `fields` is the 49-byte suffix /// and `digest` is the keccak256 hash to be signed. +/// +/// Pass `zone_id = 0` for an unscoped token valid for any zone. pub fn build_token_fields( zone_id: u32, chain_id: u64, diff --git a/crates/rpc/src/error.rs b/crates/rpc/src/error.rs index 5ea05a310..19343df4a 100644 --- a/crates/rpc/src/error.rs +++ b/crates/rpc/src/error.rs @@ -18,7 +18,7 @@ pub enum AuthError { ChainIdMismatch, #[error("zone portal mismatch")] ZonePortalMismatch, - #[error("validity window too large (max 1800s)")] + #[error("validity window too large (max 2592000s)")] WindowTooLarge, #[error("authorization token expired")] Expired, diff --git a/crates/rpc/src/provider.rs b/crates/rpc/src/provider.rs index dab7fb780..9be4c5de8 100644 --- a/crates/rpc/src/provider.rs +++ b/crates/rpc/src/provider.rs @@ -35,7 +35,7 @@ pub struct ZoneProviderConfig { pub chain_id: u64, /// ZonePortal contract address on L1. pub zone_portal: Address, - /// How long each generated token is valid. Default: 600s, max: 1800s. + /// How long each generated token is valid. Default: 600s, max: 2592000s (30 days). pub token_ttl: Duration, /// The private zone RPC URL. pub rpc_url: url::Url, diff --git a/crates/tempo-zone/tests/it/private_rpc_e2e.rs b/crates/tempo-zone/tests/it/private_rpc_e2e.rs index 646580069..45a80aaf6 100644 --- a/crates/tempo-zone/tests/it/private_rpc_e2e.rs +++ b/crates/tempo-zone/tests/it/private_rpc_e2e.rs @@ -174,7 +174,7 @@ async fn test_auth_rejection() -> eyre::Result<()> { // Valid signature but wrong chain ID → 403 let bad_token = ctx.build_bad_token( &ctx.sequencer_signer, - 0, + 1, ctx.config.chain_id + 1, Address::ZERO, ); diff --git a/crates/tempo-zone/tests/it/utils.rs b/crates/tempo-zone/tests/it/utils.rs index 1fba8dcfe..a4f08d54e 100644 --- a/crates/tempo-zone/tests/it/utils.rs +++ b/crates/tempo-zone/tests/it/utils.rs @@ -2223,6 +2223,14 @@ pub(crate) async fn start_local_zone_with_fixture( ) -> eyre::Result<(ZoneTestNode, L1Fixture)> { let zone = ZoneTestNode::start_local().await?; let fixture = L1Fixture::new(); + + // Local tests have no real L1, so the RPC fallback in resolve_transfer_policy_id + // fails. Seed pathUSD with the default allow-all policy (mirrors L1 default). + use tempo_precompiles::{PATH_USD_ADDRESS, tip403_registry::ALLOW_ALL_POLICY_ID}; + zone.policy_cache() + .write() + .set_token_policy(PATH_USD_ADDRESS, 0, ALLOW_ALL_POLICY_ID); + fixture.seed_l1_cache( zone.l1_state_cache(), Address::ZERO, From 66df45a48713789188f4f4cdc505ec7c3d73ddf3 Mon Sep 17 00:00:00 2001 From: Derek Cofausper <256792747+decofe@users.noreply.github.com> Date: Mon, 6 Apr 2026 06:08:04 +0000 Subject: [PATCH 06/12] fix: revert zonePortal addition to RPC authorization token The zonePortal field in the auth token wire format is unrelated to the deposit bounceback feature. Reverts token format back to the original 29-byte layout (version + zoneId + chainId + issuedAt + expiresAt). Co-authored-by: dankrad <6130607+dankrad@users.noreply.github.com> Amp-Thread-ID: https://ampcode.com/threads/T-019d5f52-e187-7554-b95f-59c7b789eb28 --- crates/rpc/src/auth/token.rs | 38 +++++--------- crates/rpc/src/config.rs | 2 +- crates/rpc/src/error.rs | 2 - crates/rpc/src/provider.rs | 14 ++---- crates/rpc/src/server.rs | 4 +- crates/rpc/tests/it/ws.rs | 15 +++--- crates/tempo-zone/tests/it/private_rpc_e2e.rs | 7 +-- crates/tempo-zone/tests/it/utils.rs | 49 ++++--------------- 8 files changed, 35 insertions(+), 96 deletions(-) diff --git a/crates/rpc/src/auth/token.rs b/crates/rpc/src/auth/token.rs index f0003453a..d0fe75d8e 100644 --- a/crates/rpc/src/auth/token.rs +++ b/crates/rpc/src/auth/token.rs @@ -15,9 +15,8 @@ const TEMPO_ZONE_RPC_MAGIC: [u8; 32] = { buf }; -/// Size of the fixed token fields (version + zoneId + chainId + zonePortal + issuedAt + -/// expiresAt). -const TOKEN_FIELDS_LEN: usize = 1 + 4 + 8 + 20 + 8 + 8; // 49 bytes +/// Size of the fixed token fields (version + zoneId + chainId + issuedAt + expiresAt). +const TOKEN_FIELDS_LEN: usize = 1 + 4 + 8 + 8 + 8; // 29 bytes /// HTTP header name for the authorization token. pub const X_AUTHORIZATION_TOKEN: &str = "x-authorization-token"; @@ -35,8 +34,8 @@ pub struct AuthContext { /// Parsed authorization token fields (before signature verification). /// -/// The token is a hex-encoded blob: ``. -/// The last 49 bytes are always the fixed fields; everything before is the variable-length signature. +/// The token is a hex-encoded blob: ``. +/// The last 29 bytes are always the fixed fields; everything before is the variable-length signature. /// /// See `docs/pages/protocol/privacy/rpc.md` — "Transport" and "Message" sections. #[derive(Debug, Clone)] @@ -47,13 +46,11 @@ pub struct AuthorizationToken { pub zone_id: u32, /// Chain ID. pub chain_id: u64, - /// ZonePortal address on Tempo L1. - pub zone_portal: Address, /// Issuance timestamp (unix seconds). pub issued_at: u64, /// Expiry timestamp (unix seconds). pub expires_at: u64, - /// The raw signature bytes (everything before the last 49 bytes). + /// The raw signature bytes (everything before the last 29 bytes). pub signature: Vec, /// The signing digest (keccak256 of the packed message). pub digest: B256, @@ -76,9 +73,8 @@ impl AuthorizationToken { let version = fields[0]; let zone_id = u32::from_be_bytes(fields[1..5].try_into().unwrap()); let chain_id = u64::from_be_bytes(fields[5..13].try_into().unwrap()); - let zone_portal = Address::from_slice(&fields[13..33]); - let issued_at = u64::from_be_bytes(fields[33..41].try_into().unwrap()); - let expires_at = u64::from_be_bytes(fields[41..49].try_into().unwrap()); + let issued_at = u64::from_be_bytes(fields[13..21].try_into().unwrap()); + let expires_at = u64::from_be_bytes(fields[21..29].try_into().unwrap()); // Build the signing digest let mut msg = Vec::with_capacity(32 + TOKEN_FIELDS_LEN); @@ -86,7 +82,6 @@ impl AuthorizationToken { msg.push(version); msg.extend_from_slice(&zone_id.to_be_bytes()); msg.extend_from_slice(&chain_id.to_be_bytes()); - msg.extend_from_slice(zone_portal.as_slice()); msg.extend_from_slice(&issued_at.to_be_bytes()); msg.extend_from_slice(&expires_at.to_be_bytes()); let digest = keccak256(&msg); @@ -95,7 +90,6 @@ impl AuthorizationToken { version, zone_id, chain_id, - zone_portal, issued_at, expires_at, signature, @@ -106,12 +100,7 @@ impl AuthorizationToken { /// Validate token fields against the server's zone configuration. /// /// A `zone_id` of `0` is unscoped and accepted for any zone. - pub fn validate( - &self, - expected_zone_id: u32, - expected_chain_id: u64, - expected_portal: Address, - ) -> Result<(), AuthError> { + pub fn validate(&self, expected_zone_id: u32, expected_chain_id: u64) -> Result<(), AuthError> { if self.version != 0 { return Err(AuthError::UnsupportedVersion(self.version)); } @@ -121,9 +110,6 @@ impl AuthorizationToken { if self.chain_id != expected_chain_id { return Err(AuthError::ChainIdMismatch); } - if self.zone_portal != expected_portal { - return Err(AuthError::ZonePortalMismatch); - } if self.expires_at.saturating_sub(self.issued_at) > 2_592_000 { return Err(AuthError::WindowTooLarge); } @@ -146,14 +132,13 @@ impl AuthorizationToken { /// Build the unsigned token fields and their signing digest. /// -/// Returns `(fields, digest)` where `fields` is the 49-byte suffix +/// Returns `(fields, digest)` where `fields` is the 29-byte suffix /// and `digest` is the keccak256 hash to be signed. /// /// Pass `zone_id = 0` for an unscoped token valid for any zone. pub fn build_token_fields( zone_id: u32, chain_id: u64, - zone_portal: Address, issued_at: u64, expires_at: u64, ) -> ([u8; TOKEN_FIELDS_LEN], B256) { @@ -161,9 +146,8 @@ pub fn build_token_fields( fields[0] = 0; // version fields[1..5].copy_from_slice(&zone_id.to_be_bytes()); fields[5..13].copy_from_slice(&chain_id.to_be_bytes()); - fields[13..33].copy_from_slice(zone_portal.as_slice()); - fields[33..41].copy_from_slice(&issued_at.to_be_bytes()); - fields[41..49].copy_from_slice(&expires_at.to_be_bytes()); + fields[13..21].copy_from_slice(&issued_at.to_be_bytes()); + fields[21..29].copy_from_slice(&expires_at.to_be_bytes()); let mut msg = Vec::with_capacity(32 + TOKEN_FIELDS_LEN); msg.extend_from_slice(&TEMPO_ZONE_RPC_MAGIC); diff --git a/crates/rpc/src/config.rs b/crates/rpc/src/config.rs index ff0efdbfb..649856b43 100644 --- a/crates/rpc/src/config.rs +++ b/crates/rpc/src/config.rs @@ -18,7 +18,7 @@ pub struct PrivateRpcConfig { pub zone_id: u32, /// The zone's chain ID. pub chain_id: u64, - /// The ZonePortal contract address on L1. + /// The ZonePortal contract address on L1 (used for querying deposits, not for auth tokens). pub zone_portal: Address, /// The sequencer address — callers matching this get unredacted responses. pub sequencer: Address, diff --git a/crates/rpc/src/error.rs b/crates/rpc/src/error.rs index 19343df4a..61e96fad7 100644 --- a/crates/rpc/src/error.rs +++ b/crates/rpc/src/error.rs @@ -16,8 +16,6 @@ pub enum AuthError { ZoneIdMismatch, #[error("chain ID mismatch")] ChainIdMismatch, - #[error("zone portal mismatch")] - ZonePortalMismatch, #[error("validity window too large (max 2592000s)")] WindowTooLarge, #[error("authorization token expired")] diff --git a/crates/rpc/src/provider.rs b/crates/rpc/src/provider.rs index 9be4c5de8..d0a570d5a 100644 --- a/crates/rpc/src/provider.rs +++ b/crates/rpc/src/provider.rs @@ -9,7 +9,7 @@ use std::{ time::{Duration, SystemTime, UNIX_EPOCH}, }; -use alloy_primitives::{Address, hex}; +use alloy_primitives::hex; use alloy_provider::{DynProvider, Provider, ProviderBuilder}; use alloy_signer::SignerSync; use alloy_signer_local::PrivateKeySigner; @@ -33,8 +33,6 @@ pub struct ZoneProviderConfig { pub zone_id: u32, /// Chain identifier. pub chain_id: u64, - /// ZonePortal contract address on L1. - pub zone_portal: Address, /// How long each generated token is valid. Default: 600s, max: 2592000s (30 days). pub token_ttl: Duration, /// The private zone RPC URL. @@ -107,20 +105,14 @@ fn build_provider_with_token( let now = now_secs(); let expires_at = now + config.token_ttl.as_secs(); - let (fields, digest) = build_token_fields( - config.zone_id, - config.chain_id, - config.zone_portal, - now, - expires_at, - ); + let (fields, digest) = build_token_fields(config.zone_id, config.chain_id, now, expires_at); let sig = config .signer .sign_hash_sync(&digest) .map_err(|e| eyre::eyre!("failed to sign zone auth token: {e}"))?; - // Build blob: <65-byte sig><49-byte fields> + // Build blob: <65-byte sig><29-byte fields> let mut blob = Vec::with_capacity(65 + fields.len()); blob.extend_from_slice(&sig.r().to_be_bytes::<32>()); blob.extend_from_slice(&sig.s().to_be_bytes::<32>()); diff --git a/crates/rpc/src/server.rs b/crates/rpc/src/server.rs index c5c7b3998..7bb7b7801 100644 --- a/crates/rpc/src/server.rs +++ b/crates/rpc/src/server.rs @@ -219,7 +219,7 @@ pub(crate) async fn authenticate_token( let token = auth::parse_auth_header(token_value)?; // Validate token fields against server config - token.validate(config.zone_id, config.chain_id, config.zone_portal)?; + token.validate(config.zone_id, config.chain_id)?; let signature = TempoSignature::from_bytes(&token.signature).map_err(|_| AuthError::InvalidSignature)?; @@ -400,7 +400,7 @@ mod tests { let root_account = Address::repeat_byte(0x55); let access_signer = P256SigningKey::random(&mut thread_rng()); let now = now_secs(); - let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, PORTAL, now, now + 600); + let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, now, now + 600); let (signature, key_id) = sign_keychain_signature(digest, &access_signer, root_account, 0x04) .expect("keychain signing failed"); diff --git a/crates/rpc/tests/it/ws.rs b/crates/rpc/tests/it/ws.rs index 8a33890b3..4017ac1ec 100644 --- a/crates/rpc/tests/it/ws.rs +++ b/crates/rpc/tests/it/ws.rs @@ -269,7 +269,6 @@ impl ZoneRpcApi for MockZoneRpcApi { const ZONE_ID: u32 = 1; const CHAIN_ID: u64 = 42; -const PORTAL: Address = Address::ZERO; struct TestContext { addr: std::net::SocketAddr, @@ -286,7 +285,7 @@ impl TestContext { retry_connection_interval: std::time::Duration::from_millis(100), zone_id: ZONE_ID, chain_id: CHAIN_ID, - zone_portal: PORTAL, + zone_portal: Address::ZERO, sequencer: signer.address(), }; let addr = start_private_rpc(config, Arc::new(api)).await.unwrap(); @@ -295,7 +294,7 @@ impl TestContext { fn build_token(&self) -> String { let now = now_secs(); - let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, PORTAL, now, now + 600); + let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, now, now + 600); let sig = self.signer.sign_hash_sync(&digest).expect("signing failed"); let mut blob = Vec::with_capacity(65 + fields.len()); @@ -793,7 +792,7 @@ async fn ws_roundtrip_with_p256_auth() { let ctx = TestContext::start(MockZoneRpcApi::default()).await; let signing_key = P256SigningKey::random(&mut thread_rng()); let now = now_secs(); - let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, PORTAL, now, now + 600); + let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, now, now + 600); let token = build_token_with_signature( sign_p256_signature(digest, &signing_key).expect("p256 signing should succeed"), &fields, @@ -818,7 +817,7 @@ async fn ws_roundtrip_with_webauthn_auth() { let ctx = TestContext::start(MockZoneRpcApi::default()).await; let signing_key = P256SigningKey::random(&mut thread_rng()); let now = now_secs(); - let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, PORTAL, now, now + 600); + let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, now, now + 600); let token = build_token_with_signature( sign_webauthn_signature(&signing_key, digest).expect("webauthn signing should succeed"), &fields, @@ -843,7 +842,7 @@ async fn ws_roundtrip_with_keychain_auth() { let root_account = Address::repeat_byte(0x55); let access_signer = P256SigningKey::random(&mut thread_rng()); let now = now_secs(); - let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, PORTAL, now, now + 600); + let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, now, now + 600); let (signature, key_id) = sign_keychain_signature(digest, &access_signer, root_account, 0x04) .expect("keychain signing should succeed"); let ctx = TestContext::start(MockZoneRpcApi::with_key( @@ -874,7 +873,7 @@ async fn ws_reject_unauthorized_keychain_token() { let access_signer = P256SigningKey::random(&mut thread_rng()); let ctx = TestContext::start(MockZoneRpcApi::default()).await; let now = now_secs(); - let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, PORTAL, now, now + 600); + let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, now, now + 600); let (signature, _key_id) = sign_keychain_signature(digest, &access_signer, root_account, 0x04) .expect("keychain signing should succeed"); let token = build_token_with_signature(signature, &fields); @@ -894,7 +893,7 @@ async fn ws_keychain_lookup_failure_returns_500() { let access_signer = P256SigningKey::random(&mut thread_rng()); let ctx = TestContext::start(MockZoneRpcApi::with_key_lookup_error("key lookup failed")).await; let now = now_secs(); - let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, PORTAL, now, now + 600); + let (fields, digest) = build_token_fields(ZONE_ID, CHAIN_ID, now, now + 600); let (signature, _key_id) = sign_keychain_signature(digest, &access_signer, root_account, 0x04) .expect("keychain signing should succeed"); let token = build_token_with_signature(signature, &fields); diff --git a/crates/tempo-zone/tests/it/private_rpc_e2e.rs b/crates/tempo-zone/tests/it/private_rpc_e2e.rs index 45a80aaf6..e72df4857 100644 --- a/crates/tempo-zone/tests/it/private_rpc_e2e.rs +++ b/crates/tempo-zone/tests/it/private_rpc_e2e.rs @@ -172,12 +172,7 @@ async fn test_auth_rejection() -> eyre::Result<()> { ); // Valid signature but wrong chain ID → 403 - let bad_token = ctx.build_bad_token( - &ctx.sequencer_signer, - 1, - ctx.config.chain_id + 1, - Address::ZERO, - ); + let bad_token = ctx.build_bad_token(&ctx.sequencer_signer, 1, ctx.config.chain_id + 1); let (status, _) = ctx .call_raw("eth_blockNumber", serde_json::json!([]), &bad_token) .await?; diff --git a/crates/tempo-zone/tests/it/utils.rs b/crates/tempo-zone/tests/it/utils.rs index a4f08d54e..bb9dcfba1 100644 --- a/crates/tempo-zone/tests/it/utils.rs +++ b/crates/tempo-zone/tests/it/utils.rs @@ -2262,7 +2262,6 @@ fn build_auth_token( signer: &alloy_signer_local::PrivateKeySigner, zone_id: u32, chain_id: u64, - portal: Address, ) -> String { use alloy_signer::SignerSync; use zone::rpc::auth::build_token_fields; @@ -2270,7 +2269,7 @@ fn build_auth_token( let now = now_secs(); let expires_at = now + 600; - let (fields, digest) = build_token_fields(zone_id, chain_id, portal, now, expires_at); + let (fields, digest) = build_token_fields(zone_id, chain_id, now, expires_at); let sig = signer.sign_hash_sync(&digest).expect("signing failed"); let mut blob = Vec::with_capacity(65 + fields.len()); @@ -2286,32 +2285,24 @@ fn build_auth_token_with_signature( signature: TempoSignature, zone_id: u32, chain_id: u64, - portal: Address, ) -> String { use zone::rpc::auth::build_token_fields; let now = now_secs(); let expires_at = now + 600; - let (fields, _) = build_token_fields(zone_id, chain_id, portal, now, expires_at); + let (fields, _) = build_token_fields(zone_id, chain_id, now, expires_at); auth_tokens::build_token_with_signature(signature, &fields) } -fn build_p256_auth_token( - signing_key: &P256SigningKey, - zone_id: u32, - chain_id: u64, - portal: Address, -) -> String { +fn build_p256_auth_token(signing_key: &P256SigningKey, zone_id: u32, chain_id: u64) -> String { let now = now_secs(); let expires_at = now + 600; - let (_, digest) = - zone::rpc::auth::build_token_fields(zone_id, chain_id, portal, now, expires_at); + let (_, digest) = zone::rpc::auth::build_token_fields(zone_id, chain_id, now, expires_at); build_auth_token_with_signature( sign_p256_signature(digest, signing_key).expect("p256 signing failed"), zone_id, chain_id, - portal, ) } @@ -2319,19 +2310,16 @@ fn build_webauthn_auth_token( signing_key: &P256SigningKey, zone_id: u32, chain_id: u64, - portal: Address, challenge_digest: Option, ) -> String { let now = now_secs(); let expires_at = now + 600; - let (_, digest) = - zone::rpc::auth::build_token_fields(zone_id, chain_id, portal, now, expires_at); + let (_, digest) = zone::rpc::auth::build_token_fields(zone_id, chain_id, now, expires_at); build_auth_token_with_signature( sign_webauthn_signature(signing_key, challenge_digest.unwrap_or(digest)) .expect("webauthn signing failed"), zone_id, chain_id, - portal, ) } @@ -2341,17 +2329,15 @@ fn build_keychain_auth_token( version: u8, zone_id: u32, chain_id: u64, - portal: Address, ) -> (String, Address) { let now = now_secs(); let expires_at = now + 600; - let (_, digest) = - zone::rpc::auth::build_token_fields(zone_id, chain_id, portal, now, expires_at); + let (_, digest) = zone::rpc::auth::build_token_fields(zone_id, chain_id, now, expires_at); let (signature, key_id) = sign_keychain_signature(digest, signing_key, root_account, version) .expect("keychain signing failed"); ( - build_auth_token_with_signature(signature, zone_id, chain_id, portal), + build_auth_token_with_signature(signature, zone_id, chain_id), key_id, ) } @@ -2492,28 +2478,17 @@ impl PrivateRpcTestCtx { &self.sequencer_signer, self.config.zone_id, self.config.chain_id, - self.config.zone_portal, ) } /// Build an auth token for a regular (non-sequencer) user. pub(crate) fn user_token(&self, signer: &alloy_signer_local::PrivateKeySigner) -> String { - build_auth_token( - signer, - self.config.zone_id, - self.config.chain_id, - self.config.zone_portal, - ) + build_auth_token(signer, self.config.zone_id, self.config.chain_id) } /// Build a P256 auth token for a non-sequencer caller. pub(crate) fn p256_token(&self, signing_key: &P256SigningKey) -> String { - build_p256_auth_token( - signing_key, - self.config.zone_id, - self.config.chain_id, - self.config.zone_portal, - ) + build_p256_auth_token(signing_key, self.config.zone_id, self.config.chain_id) } /// Build a WebAuthn auth token for a non-sequencer caller. @@ -2522,7 +2497,6 @@ impl PrivateRpcTestCtx { signing_key, self.config.zone_id, self.config.chain_id, - self.config.zone_portal, None, ) } @@ -2537,7 +2511,6 @@ impl PrivateRpcTestCtx { signing_key, self.config.zone_id, self.config.chain_id, - self.config.zone_portal, Some(challenge_digest), ) } @@ -2555,7 +2528,6 @@ impl PrivateRpcTestCtx { version, self.config.zone_id, self.config.chain_id, - self.config.zone_portal, ) } @@ -2615,9 +2587,8 @@ impl PrivateRpcTestCtx { signer: &alloy_signer_local::PrivateKeySigner, zone_id: u32, chain_id: u64, - portal: Address, ) -> String { - build_auth_token(signer, zone_id, chain_id, portal) + build_auth_token(signer, zone_id, chain_id) } /// Inject an empty L1 block and wait for it to be processed. From 704af1e265c052dc76a97d1a623e52e8d2c9555c Mon Sep 17 00:00:00 2001 From: Derek Cofausper <256792747+decofe@users.noreply.github.com> Date: Mon, 6 Apr 2026 06:24:03 +0000 Subject: [PATCH 07/12] fix: restore RPC auth token docs (unscoped tokens, 30-day window, no zonePortal) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reverts rpc.md to main — the zonePortal field, removal of unscoped tokens section, and 30-minute validity window were not part of the deposit bounceback feature. Co-Authored-By: dankrad <6130607+dankrad@users.noreply.github.com> Amp-Thread-ID: https://ampcode.com/threads/T-019d5f52-e187-7554-b95f-59c7b789eb28 --- docs/pages/protocol/privacy/rpc.md | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/docs/pages/protocol/privacy/rpc.md b/docs/pages/protocol/privacy/rpc.md index 0fd42b0b2..4ad5f671a 100644 --- a/docs/pages/protocol/privacy/rpc.md +++ b/docs/pages/protocol/privacy/rpc.md @@ -28,9 +28,8 @@ The signed message is the `keccak256` hash of the following packed encoding: bytes32 authorizationTokenHash = keccak256(abi.encodePacked( bytes32(0x54656d706f5a6f6e65525043), // "TempoZoneRPC" magic prefix uint8(version), // spec version (currently 0) - uint32(zoneId), // zone this key is valid for + uint32(zoneId), // zone this key is valid for (0 = unscoped) uint64(chainId), // zone chain ID (replay protection) - address(zonePortal), // ZonePortal address on Tempo uint64(issuedAt), // unix timestamp (seconds) of issuance uint64(expiresAt) // unix timestamp (seconds) of expiry )); @@ -40,6 +39,14 @@ The `version` field MUST be `0` for this version of the spec. The RPC server MUS This hash is the challenge that must be signed. Using a raw `keccak256` hash (rather than EIP-191 personal messages or EIP-712 typed data) allows all Tempo signature types to sign the same message consistently — P256 and WebAuthn signers cannot produce EIP-191 prefixed signatures. The `"TempoZoneRPC"` magic prefix provides domain separation, ensuring that authorization token hashes cannot collide with Tempo transaction hashes or other signing contexts. +### Unscoped tokens + +A `zoneId` of `0` indicates an **unscoped** authorization token that is valid for any zone. Zone IDs are assigned by `ZoneFactory` starting at 1, so `0` is never a valid zone ID. + +When the RPC server receives a token with `zoneId == 0`, it MUST skip the zone ID check and accept the token for any zone. All other validation rules (version, chain ID, expiry, signature) still apply. The `chainId` field continues to provide cross-network replay protection. + +Unscoped tokens are useful for applications and SDKs that interact with multiple zones on the same network without managing separate tokens per zone. Since authorization tokens are read-only credentials (no RPC method authenticated solely by a token may modify state), the additional exposure is limited to read access across zones the user has accounts in. + ### Signature types The authorization token signature follows the same format as [Tempo transaction signatures](/protocol/transactions/spec-tempo-transaction#signature-types). The signature type is determined by the first byte and length: @@ -109,10 +116,9 @@ This allows session keys and scoped Access Keys to authenticate to the RPC with The RPC server MUST reject authorization tokens where: -- `zoneId` does not equal the zone's configured `zoneId`. +- `zoneId` does not equal the zone's configured `zoneId` **and** `zoneId` is not `0` (an unscoped token with `zoneId == 0` is valid for any zone — see [Unscoped tokens](#unscoped-tokens)). - `chainId` does not equal the zone's configured chain ID (`eth_chainId`). -- `zonePortal` does not equal the zone's configured Tempo ZonePortal address. -- `expiresAt - issuedAt > 1800` (maximum validity window is 30 minutes). +- `expiresAt - issuedAt > 2592000` (maximum validity window is 30 days). - `expiresAt <= now` (key has expired). - `issuedAt > now + 60` (clock skew tolerance of 60 seconds into the future). - The signature is malformed or does not verify. @@ -137,10 +143,10 @@ Content-Type: application/json The `X-Authorization-Token` value is a single hex-encoded blob containing the concatenation of the signature and the authorization token fields: ``` - + ``` -The authorization token fields are always exactly 49 bytes (1 + 4 + 8 + 20 + 8 + 8). To parse the blob, the RPC server reads the **last 49 bytes** as the authorization token fields, and treats everything before them as the signature. The signature is then parsed using the same detection rules as [Tempo transaction signatures](/protocol/transactions/spec-tempo-transaction#signature-types) (secp256k1 is exactly 65 bytes; P256 starts with `0x01` and is 130 bytes; WebAuthn starts with `0x02` and is variable-length; Keychain starts with `0x03` for legacy V1 or `0x04` for V2 and is variable-length). Parsing from the end avoids any ambiguity with variable-length signature types. +The authorization token fields are always exactly 29 bytes (1 + 4 + 8 + 8 + 8). To parse the blob, the RPC server reads the **last 29 bytes** as the authorization token fields, and treats everything before them as the signature. The signature is then parsed using the same detection rules as [Tempo transaction signatures](/protocol/transactions/spec-tempo-transaction#signature-types) (secp256k1 is exactly 65 bytes; P256 starts with `0x01` and is 130 bytes; WebAuthn starts with `0x02` and is variable-length; Keychain starts with `0x03` for legacy V1 or `0x04` for V2 and is variable-length). Parsing from the end avoids any ambiguity with variable-length signature types. Requests without an authorization token receive a `401 Unauthorized` HTTP response. Requests with an expired, malformed, or unauthorized token receive `403 Forbidden`. If Keychain token verification fails because the server cannot read `AccountKeychain.getKey(...)`, the server returns `500 Internal Server Error`. @@ -485,7 +491,7 @@ In addition to standard JSON-RPC error codes, the zone RPC uses: - **Side channels via timing**: Scoped methods that must fetch data before checking authorization are subject to a mandatory 100 ms response floor (see [Timing side channels and the 100 ms speed bump](#timing-side-channels-and-the-100-ms-speed-bump)). This ensures that `eth_getTransactionByHash` for a non-existent transaction and for another user's transaction have indistinguishable response times. - **Nonce privacy**: `eth_getTransactionCount` for non-authenticated accounts returns `0x0` rather than an error. This avoids revealing whether an account exists. The constant `0x0` response is indistinguishable from a genuinely new account. -- **Authorization token replay**: Authorization tokens are scoped to a specific zone (`zoneId` and `chainId`) and a specific portal (`zonePortal`), with a maximum 30-minute window. Authorization tokens are strictly read-only credentials — no RPC method that is authenticated solely by an authorization token may modify state (see [Withdrawals](#zone-specific-rpc-methods)). The RPC server SHOULD implement nonce tracking or rate limiting to further reduce the window for abuse if a token is intercepted, but replay of a read-only token cannot move funds. +- **Authorization token replay**: Authorization tokens are scoped to a specific zone (`zoneId`) and network (`chainId`), with a maximum 30-day validity window. When `zoneId` is `0` (unscoped), the token is valid across all zones on that network. Authorization tokens are strictly read-only credentials — no RPC method that is authenticated solely by an authorization token may modify state (see [Withdrawals](#zone-specific-rpc-methods)). The RPC server SHOULD implement nonce tracking or rate limiting to further reduce the window for abuse if a token is intercepted, but replay of a read-only token cannot move funds. - **Simulation override extensions**: Some Ethereum clients support non-standard simulation extensions (state override sets and block override objects) on `eth_call`/`eth_estimateGas`. Privacy zones MUST reject these extensions for non-sequencer callers, because they can bypass or distort normal state access assumptions used by this spec's privacy model. - **Keychain key revocation and expiry**: When a root account revokes a Keychain key on-chain, the RPC server MUST stop accepting that key within 1 second of importing the block that contains the revocation. Cached Keychain verifications MUST also honor key expiry: a cache entry MUST expire no later than `min(authorizationToken.expiresAt, keyExpiry)` where `keyExpiry` is read from `AccountKeychain.getKey(...)`. In the current `AccountKeychain` implementation, inactive or revoked keys are surfaced as `keyId == 0` and `expiry == 0`, so those results MUST be treated as immediately invalid rather than "never expires." The recommended implementation is event-driven: the zone node watches for `KeyRevoked(account, publicKey)` events emitted by the AccountKeychain precompile during block execution and immediately evicts matching entries from the authorization token cache. This requires no cryptography — just a cache lookup and delete. As a fallback, implementations MAY poll the precompile via `getKey(user_address, keyId)`, but the 1-second deadline still applies. - **P256/WebAuthn key compromise**: Unlike secp256k1, P256 and WebAuthn keys include the public key in the signature. This means the public key is visible to the RPC server on every request. This is not a security concern (public keys are public), but implementations should be aware that the key material is transmitted in the clear over the connection. From d8003df7f5534106d0cb7993e3cc6e1f51a071f5 Mon Sep 17 00:00:00 2001 From: Derek Cofausper <256792747+decofe@users.noreply.github.com> Date: Mon, 6 Apr 2026 06:28:20 +0000 Subject: [PATCH 08/12] fix: cargo fmt Co-Authored-By: dankrad <6130607+dankrad@users.noreply.github.com> Amp-Thread-ID: https://ampcode.com/threads/T-019d5f52-e187-7554-b95f-59c7b789eb28 --- crates/tempo-zone/tests/it/utils.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/crates/tempo-zone/tests/it/utils.rs b/crates/tempo-zone/tests/it/utils.rs index bb9dcfba1..a73ae83ec 100644 --- a/crates/tempo-zone/tests/it/utils.rs +++ b/crates/tempo-zone/tests/it/utils.rs @@ -2493,12 +2493,7 @@ impl PrivateRpcTestCtx { /// Build a WebAuthn auth token for a non-sequencer caller. pub(crate) fn webauthn_token(&self, signing_key: &P256SigningKey) -> String { - build_webauthn_auth_token( - signing_key, - self.config.zone_id, - self.config.chain_id, - None, - ) + build_webauthn_auth_token(signing_key, self.config.zone_id, self.config.chain_id, None) } /// Build a WebAuthn auth token with an overridden challenge digest. From b846de573e9959287af49d645b14a5095955dd4c Mon Sep 17 00:00:00 2001 From: Derek Cofausper <256792747+decofe@users.noreply.github.com> Date: Mon, 6 Apr 2026 06:31:34 +0000 Subject: [PATCH 09/12] fix: revert portal-in-auth-token changes from private_rpc.rs tests Co-Authored-By: dankrad <6130607+dankrad@users.noreply.github.com> Amp-Thread-ID: https://ampcode.com/threads/T-019d5f52-e187-7554-b95f-59c7b789eb28 --- crates/tempo-zone/tests/it/private_rpc.rs | 88 +++++++++-------------- 1 file changed, 35 insertions(+), 53 deletions(-) diff --git a/crates/tempo-zone/tests/it/private_rpc.rs b/crates/tempo-zone/tests/it/private_rpc.rs index 7086ca2ea..9a0b88ab7 100644 --- a/crates/tempo-zone/tests/it/private_rpc.rs +++ b/crates/tempo-zone/tests/it/private_rpc.rs @@ -21,13 +21,10 @@ fn build_token_blob( version: u8, zone_id: u32, chain_id: u64, - portal: Address, issued_at: u64, expires_at: u64, ) -> Vec { - let (mut fields, _digest) = - build_token_fields(zone_id, chain_id, portal, issued_at, expires_at); - // build_token_fields always sets version=0; override for tests that need a different version. + let (mut fields, _digest) = build_token_fields(zone_id, chain_id, issued_at, expires_at); fields[0] = version; let mut blob = vec![0u8; 65]; // fake secp256k1 sig blob.extend_from_slice(&fields); @@ -38,11 +35,10 @@ fn make_test_token( version: u8, zone_id: u32, chain_id: u64, - portal: Address, issued_at: u64, expires_at: u64, ) -> AuthorizationToken { - let blob = build_token_blob(version, zone_id, chain_id, portal, issued_at, expires_at); + let blob = build_token_blob(version, zone_id, chain_id, issued_at, expires_at); AuthorizationToken::parse(&blob).unwrap() } @@ -51,14 +47,12 @@ fn make_test_token( #[test] fn parse_token_fields() { let now = now_secs(); - let portal = Address::repeat_byte(0xAA); - let token = make_test_token(0, 42, 1337, portal, now, now + 600); + let token = make_test_token(0, 42, 1337, now, now + 600); assert_eq!(token.version, 0); assert_eq!(token.zone_id, 42); assert_eq!(token.chain_id, 1337); - assert_eq!(token.zone_portal, portal); assert_eq!(token.issued_at, now); assert_eq!(token.expires_at, now + 600); assert_eq!(token.signature.len(), 65); @@ -66,8 +60,8 @@ fn parse_token_fields() { #[test] fn parse_token_too_short() { - // 49 bytes = exactly the message length, no room for a signature - let blob = vec![0u8; 49]; + // 29 bytes = exactly the message length, no room for a signature + let blob = vec![0u8; 29]; assert!(AuthorizationToken::parse(&blob).is_err()); // Even shorter @@ -78,11 +72,10 @@ fn parse_token_too_short() { fn parse_unknown_signature_length() { // 50-byte signature (not 65 or 130, and first byte is not 0x02/0x03) → should error let mut blob = vec![0u8; 50]; - // 49 bytes of fields + // 29 bytes of fields blob.push(0); blob.extend_from_slice(&1u32.to_be_bytes()); blob.extend_from_slice(&1u64.to_be_bytes()); - blob.extend_from_slice(&[0u8; 20]); let now = now_secs(); blob.extend_from_slice(&now.to_be_bytes()); blob.extend_from_slice(&(now + 600).to_be_bytes()); @@ -93,17 +86,15 @@ fn parse_unknown_signature_length() { #[test] fn digest_is_deterministic() { - let portal = Address::repeat_byte(0xCC); - let t1 = make_test_token(0, 1, 2, portal, 1000, 1600); - let t2 = make_test_token(0, 1, 2, portal, 1000, 1600); + let t1 = make_test_token(0, 1, 2, 1000, 1600); + let t2 = make_test_token(0, 1, 2, 1000, 1600); assert_eq!(t1.digest, t2.digest); } #[test] fn digest_changes_with_params() { - let portal = Address::repeat_byte(0xCC); - let t1 = make_test_token(0, 1, 2, portal, 1000, 1600); - let t3 = make_test_token(0, 1, 3, portal, 1000, 1600); + let t1 = make_test_token(0, 1, 2, 1000, 1600); + let t3 = make_test_token(0, 1, 3, 1000, 1600); assert_ne!(t1.digest, t3.digest); } @@ -112,69 +103,60 @@ fn digest_changes_with_params() { #[test] fn validate_accepts_valid_token() { let now = now_secs(); - let portal = Address::repeat_byte(0xBB); - let token = make_test_token(0, 42, 1337, portal, now, now + 600); - assert!(token.validate(42, 1337, portal).is_ok()); + let token = make_test_token(0, 42, 1337, now, now + 600); + assert!(token.validate(42, 1337).is_ok()); } #[test] fn validate_rejects_wrong_version() { let now = now_secs(); - let portal = Address::repeat_byte(0xBB); - let token = make_test_token(1, 42, 1337, portal, now, now + 600); - assert!(token.validate(42, 1337, portal).is_err()); + let token = make_test_token(1, 42, 1337, now, now + 600); + assert!(token.validate(42, 1337).is_err()); } #[test] fn validate_rejects_zone_id_mismatch() { let now = now_secs(); - let portal = Address::repeat_byte(0xBB); - let token = make_test_token(0, 42, 1337, portal, now, now + 600); - assert!(token.validate(99, 1337, portal).is_err()); + let token = make_test_token(0, 42, 1337, now, now + 600); + assert!(token.validate(99, 1337).is_err()); } #[test] -fn validate_rejects_chain_id_mismatch() { +fn validate_accepts_unscoped_zone_id() { let now = now_secs(); - let portal = Address::repeat_byte(0xBB); - let token = make_test_token(0, 42, 1337, portal, now, now + 600); - assert!(token.validate(42, 9999, portal).is_err()); + let token = make_test_token(0, 0, 1337, now, now + 600); + assert!(token.validate(42, 1337).is_ok()); + assert!(token.validate(99, 1337).is_ok()); } #[test] -fn validate_rejects_portal_mismatch() { +fn validate_rejects_chain_id_mismatch() { let now = now_secs(); - let portal = Address::repeat_byte(0xBB); - let other = Address::repeat_byte(0xCC); - let token = make_test_token(0, 42, 1337, portal, now, now + 600); - assert!(token.validate(42, 1337, other).is_err()); + let token = make_test_token(0, 42, 1337, now, now + 600); + assert!(token.validate(42, 9999).is_err()); } #[test] fn validate_rejects_expired() { let now = now_secs(); - let portal = Address::repeat_byte(0xBB); - // Token that expired 100s ago - let token = make_test_token(0, 42, 1337, portal, now - 700, now - 100); - assert!(token.validate(42, 1337, portal).is_err()); + let token = make_test_token(0, 42, 1337, now - 700, now - 100); + assert!(token.validate(42, 1337).is_err()); } #[test] fn validate_rejects_window_too_large() { let now = now_secs(); - let portal = Address::repeat_byte(0xBB); - // 2000s window > 1800s max - let token = make_test_token(0, 42, 1337, portal, now, now + 2000); - assert!(token.validate(42, 1337, portal).is_err()); + // 31 days > 30-day max + let token = make_test_token(0, 42, 1337, now, now + 31 * 86400); + assert!(token.validate(42, 1337).is_err()); } #[test] fn validate_rejects_issued_at_far_future() { let now = now_secs(); - let portal = Address::repeat_byte(0xBB); // issuedAt is 200s in the future (> 60s max skew) - let token = make_test_token(0, 42, 1337, portal, now + 200, now + 800); - assert!(token.validate(42, 1337, portal).is_err()); + let token = make_test_token(0, 42, 1337, now + 200, now + 800); + assert!(token.validate(42, 1337).is_err()); } #[tokio::test] @@ -183,7 +165,7 @@ async fn tempo_signature_roundtrip_secp256k1_from_token_bytes() { let signer = PrivateKeySigner::random(); let now = now_secs(); - let (fields, digest) = build_token_fields(1, 2, Address::ZERO, now, now + 600); + let (fields, digest) = build_token_fields(1, 2, now, now + 600); let sig = signer.sign_hash(&digest).await.unwrap(); let mut sig_bytes = Vec::with_capacity(65); @@ -215,7 +197,7 @@ fn tempo_signature_rejects_wrong_secp256k1_lengths() { fn tempo_signature_roundtrip_p256_from_token_bytes() { let signing_key = P256SigningKey::random(&mut thread_rng()); let now = now_secs(); - let (fields, digest) = build_token_fields(1, 2, Address::ZERO, now, now + 600); + let (fields, digest) = build_token_fields(1, 2, now, now + 600); let expected = sign_p256_signature(digest, &signing_key) .expect("p256 signing should succeed") .recover_signer(&digest) @@ -234,7 +216,7 @@ fn tempo_signature_roundtrip_p256_from_token_bytes() { fn tempo_signature_roundtrip_webauthn_from_token_bytes() { let signing_key = P256SigningKey::random(&mut thread_rng()); let now = now_secs(); - let (fields, digest) = build_token_fields(1, 2, Address::ZERO, now, now + 600); + let (fields, digest) = build_token_fields(1, 2, now, now + 600); let signature = sign_webauthn_signature(&signing_key, digest).expect("webauthn signing should succeed"); let expected = signature @@ -252,7 +234,7 @@ fn tempo_signature_roundtrip_keychain_v1_from_token_bytes() { let signing_key = P256SigningKey::random(&mut thread_rng()); let root_account = Address::repeat_byte(0x44); let now = now_secs(); - let (fields, digest) = build_token_fields(1, 2, Address::ZERO, now, now + 600); + let (fields, digest) = build_token_fields(1, 2, now, now + 600); let (signature, expected_key_id) = sign_keychain_signature(digest, &signing_key, root_account, 0x03) .expect("keychain signing should succeed"); @@ -274,7 +256,7 @@ fn tempo_signature_roundtrip_keychain_v2_from_token_bytes() { let signing_key = P256SigningKey::random(&mut thread_rng()); let root_account = Address::repeat_byte(0x55); let now = now_secs(); - let (fields, digest) = build_token_fields(1, 2, Address::ZERO, now, now + 600); + let (fields, digest) = build_token_fields(1, 2, now, now + 600); let (signature, expected_key_id) = sign_keychain_signature(digest, &signing_key, root_account, 0x04) .expect("keychain signing should succeed"); From 086980ea52a485995e22c7ddd4bf908e12e5e9cd Mon Sep 17 00:00:00 2001 From: Derek Cofausper <256792747+decofe@users.noreply.github.com> Date: Mon, 6 Apr 2026 06:44:06 +0000 Subject: [PATCH 10/12] fix: remove unrelated changes from deposit bounceback PR - Remove .amp/tools (benchmarking toolbox wrappers) - Remove .mergify.yml (CI config) - Remove tempo.nu (benchmarking script) - Revert Justfile portal-in-token auth changes - Revert rpc/Cargo.toml tempo-compat feature (not needed) - Restore ztip20.rs policy resolution error tests Co-authored-by: dankrad <6130607+dankrad@users.noreply.github.com> Amp-Thread-ID: https://ampcode.com/threads/T-019d5f52-e187-7554-b95f-59c7b789eb28 --- .amp/tools/tempo-bench | 66 ---- .amp/tools/tempo-infra | 31 -- .amp/tools/tempo-kill | 15 - .amp/tools/tempo-localnet | 60 --- .mergify.yml | 8 - Justfile | 4 +- crates/precompiles/src/ztip20.rs | 40 ++ crates/rpc/Cargo.toml | 2 +- tempo.nu | 629 ------------------------------- 9 files changed, 42 insertions(+), 813 deletions(-) delete mode 100755 .amp/tools/tempo-bench delete mode 100755 .amp/tools/tempo-infra delete mode 100755 .amp/tools/tempo-kill delete mode 100755 .amp/tools/tempo-localnet delete mode 100644 .mergify.yml delete mode 100755 tempo.nu diff --git a/.amp/tools/tempo-bench b/.amp/tools/tempo-bench deleted file mode 100755 index 3cb0a52b7..000000000 --- a/.amp/tools/tempo-bench +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env bash -# Amp toolbox tool: Run a full Tempo benchmark - -if [ "$TOOLBOX_ACTION" = "describe" ]; then - cat <<'EOF' -name: tempo-bench -description: Run a full Tempo benchmark with observability stack, nodes, and tempo-bench. Use this instead of manually running nu tempo.nu bench. -preset: string Transaction type preset: tip20, erc20, swap, order, or tempo-mix (required unless bench_args provided) -mode: string Mode: dev or consensus (default: consensus) -tps: number Target transactions per second (default: 10000) -duration: number Duration in seconds (default: 30) -accounts: number Number of accounts (default: 1000) -nodes: number Number of consensus nodes (default: 3, consensus mode only) -genesis: string Custom genesis file path (skips generation) -reset: boolean Reset localnet before starting (default: false) -loud: boolean Show all node logs (default: false, only WARN/ERROR shown) -samply: boolean Profile nodes with samply (default: false) -samply_args: string Additional samply arguments (space-separated) -profile: string Cargo build profile (default: profiling) -features: string Cargo features (default: jemalloc,asm-keccak) -node_args: string Additional node arguments (space-separated) -bench_args: string Additional tempo-bench arguments (space-separated) -EOF - exit 0 -fi - -if [ "$TOOLBOX_ACTION" = "execute" ]; then - input=$(cat) - - preset=$(echo "$input" | grep -E '^preset:' | sed 's/^preset: *//') - mode=$(echo "$input" | grep -E '^mode:' | sed 's/^mode: *//') - tps=$(echo "$input" | grep -E '^tps:' | sed 's/^tps: *//') - duration=$(echo "$input" | grep -E '^duration:' | sed 's/^duration: *//') - accounts=$(echo "$input" | grep -E '^accounts:' | sed 's/^accounts: *//') - nodes=$(echo "$input" | grep -E '^nodes:' | sed 's/^nodes: *//') - genesis=$(echo "$input" | grep -E '^genesis:' | sed 's/^genesis: *//') - reset=$(echo "$input" | grep -E '^reset:' | sed 's/^reset: *//') - loud=$(echo "$input" | grep -E '^loud:' | sed 's/^loud: *//') - samply=$(echo "$input" | grep -E '^samply:' | sed 's/^samply: *//') - samply_args=$(echo "$input" | grep -E '^samply_args:' | sed 's/^samply_args: *//') - profile=$(echo "$input" | grep -E '^profile:' | sed 's/^profile: *//') - features=$(echo "$input" | grep -E '^features:' | sed 's/^features: *//') - node_args=$(echo "$input" | grep -E '^node_args:' | sed 's/^node_args: *//') - bench_args=$(echo "$input" | grep -E '^bench_args:' | sed 's/^bench_args: *//') - - cmd="nu tempo.nu bench" - - [ -n "$preset" ] && cmd="$cmd --preset $preset" - [ -n "$mode" ] && cmd="$cmd --mode $mode" - [ -n "$tps" ] && cmd="$cmd --tps $tps" - [ -n "$duration" ] && cmd="$cmd --duration $duration" - [ -n "$accounts" ] && cmd="$cmd --accounts $accounts" - [ -n "$nodes" ] && cmd="$cmd --nodes $nodes" - [ -n "$genesis" ] && cmd="$cmd --genesis $genesis" - [ "$reset" = "true" ] && cmd="$cmd --reset" - [ "$loud" = "true" ] && cmd="$cmd --loud" - [ "$samply" = "true" ] && cmd="$cmd --samply" - [ -n "$samply_args" ] && cmd="$cmd --samply-args=\"$samply_args\"" - [ -n "$profile" ] && cmd="$cmd --profile $profile" - [ -n "$features" ] && cmd="$cmd --features $features" - [ -n "$node_args" ] && cmd="$cmd --node-args=\"$node_args\"" - [ -n "$bench_args" ] && cmd="$cmd --bench-args=\"$bench_args\"" - - echo "Running: $cmd" - eval "$cmd" -fi diff --git a/.amp/tools/tempo-infra b/.amp/tools/tempo-infra deleted file mode 100755 index 36d218a3d..000000000 --- a/.amp/tools/tempo-infra +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash -# Amp toolbox tool: Manage the observability stack (Grafana + Prometheus) - -if [ "$TOOLBOX_ACTION" = "describe" ]; then - cat <<'EOF' -name: tempo-infra -description: Start or stop the observability stack (Grafana + Prometheus) for benchmarking. Use this instead of manually running nu tempo.nu infra up/down. -action: string Action to perform: up or down (required) -EOF - exit 0 -fi - -if [ "$TOOLBOX_ACTION" = "execute" ]; then - input=$(cat) - - action=$(echo "$input" | grep -E '^action:' | sed 's/^action: *//') - - if [ -z "$action" ]; then - echo "Error: action is required (up or down)" - exit 1 - fi - - if [ "$action" != "up" ] && [ "$action" != "down" ]; then - echo "Error: action must be 'up' or 'down'" - exit 1 - fi - - cmd="nu tempo.nu infra $action" - echo "Running: $cmd" - eval "$cmd" -fi diff --git a/.amp/tools/tempo-kill b/.amp/tools/tempo-kill deleted file mode 100755 index efb67cb73..000000000 --- a/.amp/tools/tempo-kill +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash -# Amp toolbox tool: Kill running tempo processes and cleanup - -if [ "$TOOLBOX_ACTION" = "describe" ]; then - cat <<'EOF' -name: tempo-kill -description: Kill any running tempo processes and cleanup stale IPC sockets. Use this instead of manually running nu tempo.nu kill. -EOF - exit 0 -fi - -if [ "$TOOLBOX_ACTION" = "execute" ]; then - echo "Running: nu tempo.nu kill" - nu tempo.nu kill -fi diff --git a/.amp/tools/tempo-localnet b/.amp/tools/tempo-localnet deleted file mode 100755 index 428ced9dd..000000000 --- a/.amp/tools/tempo-localnet +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env bash -# Amp toolbox tool: Run Tempo node(s) for benchmarking - -if [ "$TOOLBOX_ACTION" = "describe" ]; then - cat <<'EOF' -name: tempo-localnet -description: Run Tempo node(s) for benchmarking. Supports dev mode (single node) or consensus mode (multiple validators). Use this instead of manually running nu tempo.nu localnet. -mode: string Mode: dev or consensus (default: dev) -nodes: number Number of validators for consensus mode (default: 3) -accounts: number Number of genesis accounts (default: 1000) -genesis: string Custom genesis file path (skips generation) -reset: boolean Wipe and regenerate localnet data (default: false) -loud: boolean Show all node logs (default: false, only WARN/ERROR shown) -samply: boolean Enable samply profiling for foreground node (default: false) -samply_args: string Additional samply arguments (space-separated) -profile: string Cargo build profile (default: profiling) -features: string Cargo features (default: jemalloc,asm-keccak) -node_args: string Additional node arguments (space-separated) -skip_build: boolean Skip building the binary (default: false) -force: boolean Kill dangling processes without prompting (default: false) -EOF - exit 0 -fi - -if [ "$TOOLBOX_ACTION" = "execute" ]; then - input=$(cat) - - mode=$(echo "$input" | grep -E '^mode:' | sed 's/^mode: *//') - nodes=$(echo "$input" | grep -E '^nodes:' | sed 's/^nodes: *//') - accounts=$(echo "$input" | grep -E '^accounts:' | sed 's/^accounts: *//') - genesis=$(echo "$input" | grep -E '^genesis:' | sed 's/^genesis: *//') - reset=$(echo "$input" | grep -E '^reset:' | sed 's/^reset: *//') - loud=$(echo "$input" | grep -E '^loud:' | sed 's/^loud: *//') - samply=$(echo "$input" | grep -E '^samply:' | sed 's/^samply: *//') - samply_args=$(echo "$input" | grep -E '^samply_args:' | sed 's/^samply_args: *//') - profile=$(echo "$input" | grep -E '^profile:' | sed 's/^profile: *//') - features=$(echo "$input" | grep -E '^features:' | sed 's/^features: *//') - node_args=$(echo "$input" | grep -E '^node_args:' | sed 's/^node_args: *//') - skip_build=$(echo "$input" | grep -E '^skip_build:' | sed 's/^skip_build: *//') - force=$(echo "$input" | grep -E '^force:' | sed 's/^force: *//') - - cmd="nu tempo.nu localnet" - - [ -n "$mode" ] && cmd="$cmd --mode $mode" - [ -n "$nodes" ] && cmd="$cmd --nodes $nodes" - [ -n "$accounts" ] && cmd="$cmd --accounts $accounts" - [ -n "$genesis" ] && cmd="$cmd --genesis $genesis" - [ "$reset" = "true" ] && cmd="$cmd --reset" - [ "$loud" = "true" ] && cmd="$cmd --loud" - [ "$samply" = "true" ] && cmd="$cmd --samply" - [ -n "$samply_args" ] && cmd="$cmd --samply-args=\"$samply_args\"" - [ -n "$profile" ] && cmd="$cmd --profile $profile" - [ -n "$features" ] && cmd="$cmd --features $features" - [ -n "$node_args" ] && cmd="$cmd --node-args=\"$node_args\"" - [ "$skip_build" = "true" ] && cmd="$cmd --skip-build" - [ "$force" = "true" ] && cmd="$cmd --force" - - echo "Running: $cmd" - eval "$cmd" -fi diff --git a/.mergify.yml b/.mergify.yml deleted file mode 100644 index 339920c94..000000000 --- a/.mergify.yml +++ /dev/null @@ -1,8 +0,0 @@ -pull_request_rules: - - name: add "S-breaking-stf" label when the title contains "!" - conditions: - - title ~= ^.*!(.*).* - actions: - label: - toggle: - - S-breaking-stf diff --git a/Justfile b/Justfile index 4ddfcb964..a8c62d0de 100644 --- a/Justfile +++ b/Justfile @@ -587,7 +587,6 @@ zone-auth-token name: exit 1 fi ZONE_ID=$(jq -r '.zoneId' "$ZONE_JSON") - PORTAL=$(jq -r '.portal' "$ZONE_JSON") GENESIS_JSON="generated/{{name}}/genesis.json" CHAIN_ID=$(jq -r '.config.chainId' "$GENESIS_JSON") NOW=$(date +%s) @@ -596,10 +595,9 @@ zone-auth-token name: VERSION="00" ZONE_ID_HEX=$(printf '%08x' "$ZONE_ID") CHAIN_ID_HEX=$(printf '%016x' "$CHAIN_ID") - PORTAL_HEX=$(echo "$PORTAL" | sed 's/0x//' | tr '[:upper:]' '[:lower:]') ISSUED_HEX=$(printf '%016x' "$NOW") EXPIRES_HEX=$(printf '%016x' "$EXPIRES") - FIELDS="${VERSION}${ZONE_ID_HEX}${CHAIN_ID_HEX}${PORTAL_HEX}${ISSUED_HEX}${EXPIRES_HEX}" + FIELDS="${VERSION}${ZONE_ID_HEX}${CHAIN_ID_HEX}${ISSUED_HEX}${EXPIRES_HEX}" DIGEST=$(cast keccak "0x${MAGIC}${FIELDS}") SIG=$(cast wallet sign --no-hash "$DIGEST" --private-key "$PK") SIG_HEX=$(echo "$SIG" | sed 's/0x//') diff --git a/crates/precompiles/src/ztip20.rs b/crates/precompiles/src/ztip20.rs index 673e6f625..9108cd4b2 100644 --- a/crates/precompiles/src/ztip20.rs +++ b/crates/precompiles/src/ztip20.rs @@ -1100,6 +1100,46 @@ mod tests { Ok(()) } + #[test] + fn transfer_fails_closed_on_policy_resolution_error() -> TestResult { + let mut harness = PrecompileHarness::new(MockPolicyProvider::failing())?; + + let calldata: Bytes = ITIP20::transferCall { + to: harness.bob, + amount: U256::from(100u64), + } + .abi_encode() + .into(); + + let result = harness.call(harness.alice, calldata, 100_000, false); + assert!( + result.is_err(), + "transfer must fail when policy resolution errors" + ); + + Ok(()) + } + + #[test] + fn mint_defers_to_l1_on_policy_resolution_error() -> TestResult { + let mut harness = PrecompileHarness::new(MockPolicyProvider::failing())?; + + let calldata: Bytes = ITIP20::mintCall { + to: harness.alice, + amount: U256::from(100u64), + } + .abi_encode() + .into(); + + let result = harness.call(harness.issuer, calldata, 100_000, false); + assert!( + result.is_ok(), + "mint must proceed when policy resolution errors (L1 enforces policy at deposit time)" + ); + + Ok(()) + } + #[test] fn has_role_enforces_account_or_sequencer_access() -> TestResult { let mut harness = PrecompileHarness::new(MockPolicyProvider::allow_all())?; diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml index bce25a906..b662c426b 100644 --- a/crates/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] # tempo -tempo-alloy = { workspace = true, features = ["tempo-compat"] } +tempo-alloy.workspace = true tempo-contracts.workspace = true tempo-primitives.workspace = true diff --git a/tempo.nu b/tempo.nu deleted file mode 100755 index c55b4c23b..000000000 --- a/tempo.nu +++ /dev/null @@ -1,629 +0,0 @@ -#!/usr/bin/env nu - -# Tempo local utilities - -const BENCH_DIR = "contrib/bench" -const LOCALNET_DIR = "localnet" -const LOGS_DIR = "contrib/bench/logs" -const RUSTFLAGS = "-C target-cpu=native" -const DEFAULT_PROFILE = "profiling" -const DEFAULT_FEATURES = "jemalloc,asm-keccak" - -# Preset weight configurations: [tip20, erc20, swap, order] -const PRESETS = { - tip20: [1.0, 0.0, 0.0, 0.0], - erc20: [0.0, 1.0, 0.0, 0.0], - swap: [0.0, 0.0, 1.0, 0.0], - order: [0.0, 0.0, 0.0, 1.0], - "tempo-mix": [0.8, 0, 0.19, 0.01] -} - -# ============================================================================ -# Helper functions -# ============================================================================ - -# Convert consensus port to node index (e.g., 8000 -> 0, 8100 -> 1) -def port-to-node-index [port: int] { - ($port - 8000) / 100 | into int -} - -# Build log filter args based on --loud flag -def log-filter-args [loud: bool] { - if $loud { [] } else { ["--log.stdout.filter" "warn"] } -} - -# Wrap command with samply if enabled -def wrap-samply [cmd: list, samply: bool, samply_args: list] { - if $samply { - ["samply" "record" ...$samply_args "--" ...$cmd] - } else { - $cmd - } -} - -# Validate mode is either "dev" or "consensus" -def validate-mode [mode: string] { - if $mode != "dev" and $mode != "consensus" { - print $"Unknown mode: ($mode). Use 'dev' or 'consensus'." - exit 1 - } -} - -# Build tempo binary with cargo -def build-tempo [bins: list, profile: string, features: string] { - let bin_args = ($bins | each { |bin| ["--bin" $bin] } | flatten) - let build_cmd = ["cargo" "build" "--profile" $profile "--features" $features] | append $bin_args - print $"Building ($bins | str join ', '): `($build_cmd | str join ' ')`..." - with-env { RUSTFLAGS: $RUSTFLAGS } { - run-external ($build_cmd | first) ...($build_cmd | skip 1) - } -} - -# Find tempo process PIDs (excluding tempo-bench) -def find-tempo-pids [] { - ps | where name =~ "tempo" | where name !~ "tempo-bench" | get pid -} - -# ============================================================================ -# Infra commands -# ============================================================================ - -# Start the observability stack (Grafana + Prometheus) -def "main infra up" [] { - print "Starting observability stack..." - docker compose -f $"($BENCH_DIR)/docker-compose.yml" up -d - print "Grafana available at http://localhost:3000 (admin/admin)" - print "Prometheus available at http://localhost:9090" -} - -# Stop the observability stack -def "main infra down" [] { - print "Stopping observability stack..." - docker compose -f $"($BENCH_DIR)/docker-compose.yml" down -} - -# ============================================================================ -# Kill command -# ============================================================================ - -# Kill any running tempo processes and cleanup -def "main kill" [ - --prompt # Prompt before killing (for interactive use) -] { - let pids = (find-tempo-pids) - let has_stale_ipc = ("/tmp/reth.ipc" | path exists) - - if ($pids | length) == 0 and not $has_stale_ipc { - print "No tempo processes or stale IPC socket found." - return - } - - if ($pids | length) > 0 { - print $"Found ($pids | length) running tempo process\(es\)." - } - if $has_stale_ipc { - print "Found stale /tmp/reth.ipc socket." - } - - let should_kill = if $prompt { - let answer = (input "Clean up? [Y/n] " | str trim | str downcase) - $answer == "" or $answer == "y" or $answer == "yes" - } else { - true - } - - if not $should_kill { - print "Aborting." - exit 1 - } - - if ($pids | length) > 0 { - print $"Sending SIGINT to ($pids | length) tempo processes..." - for pid in $pids { - kill -s 2 $pid - } - } - - # Remove stale IPC socket - if $has_stale_ipc { - rm /tmp/reth.ipc - print "Removed /tmp/reth.ipc" - } - print "Done." -} - -# ============================================================================ -# Localnet command -# ============================================================================ - -# Run Tempo localnet -def "main localnet" [ - --mode: string = "dev" # Mode: "dev" or "consensus" - --nodes: int = 3 # Number of validators (consensus mode) - --accounts: int = 1000 # Number of genesis accounts - --genesis: string = "" # Custom genesis file path (skips generation) - --samply # Enable samply profiling (foreground node only) - --samply-args: string = "" # Additional samply arguments (space-separated) - --reset # Wipe and regenerate localnet data - --profile: string = $DEFAULT_PROFILE # Cargo build profile - --features: string = $DEFAULT_FEATURES # Cargo features - --loud # Show all node logs (WARN/ERROR shown by default) - --node-args: string = "" # Additional node arguments (space-separated) - --skip-build # Skip building (assumes binary is already built) - --force # Kill dangling processes without prompting -] { - validate-mode $mode - - # Check for dangling processes or stale IPC socket - let pids = (find-tempo-pids) - let has_stale_ipc = ("/tmp/reth.ipc" | path exists) - if ($pids | length) > 0 or $has_stale_ipc { - main kill --prompt=($force | not $in) - } - - # Parse custom args - let extra_args = if $node_args == "" { [] } else { $node_args | split row " " } - let samply_args_list = if $samply_args == "" { [] } else { $samply_args | split row " " } - - # Build first (unless skipped) - if not $skip_build { - build-tempo ["tempo"] $profile $features - } - - if $mode == "dev" { - if $nodes != 3 { - print "Error: --nodes is only valid with --mode consensus" - exit 1 - } - run-dev-node $accounts $genesis $samply $samply_args_list $reset $profile $loud $extra_args - } else { - run-consensus-nodes $nodes $accounts $genesis $samply $samply_args_list $reset $profile $loud $extra_args - } -} - -# ============================================================================ -# Dev mode -# ============================================================================ - -def run-dev-node [accounts: int, genesis: string, samply: bool, samply_args: list, reset: bool, profile: string, loud: bool, extra_args: list] { - let genesis_path = if $genesis != "" { - $genesis - } else { - let default_genesis = $"($LOCALNET_DIR)/genesis.json" - let needs_generation = $reset or (not ($default_genesis | path exists)) - - if $needs_generation { - if $reset { - print "Resetting localnet data..." - } else { - print "Genesis not found, generating..." - } - rm -rf $LOCALNET_DIR - mkdir $LOCALNET_DIR - print $"Generating genesis with ($accounts) accounts..." - cargo run -p tempo-xtask --profile $profile -- generate-genesis --output $LOCALNET_DIR -a $accounts --no-dkg-in-genesis - } - $default_genesis - } - - let tempo_bin = if $profile == "dev" { - "./target/debug/tempo" - } else { - $"./target/($profile)/tempo" - } - let datadir = $"($LOCALNET_DIR)/reth" - let log_dir = $"($LOCALNET_DIR)/logs" - - let args = (build-base-args $genesis_path $datadir $log_dir 8545 9001) - | append (build-dev-args) - | append (log-filter-args $loud) - | append $extra_args - - let cmd = wrap-samply [$tempo_bin ...$args] $samply $samply_args - print $"Running dev node: `($cmd | str join ' ')`..." - run-external ($cmd | first) ...($cmd | skip 1) -} - -# Build base node arguments shared between dev and consensus modes -def build-base-args [genesis_path: string, datadir: string, log_dir: string, http_port: int, reth_metrics_port: int] { - [ - "node" - "--chain" $genesis_path - "--datadir" $datadir - "--http" - "--http.addr" "0.0.0.0" - "--http.port" $"($http_port)" - "--http.api" "all" - "--metrics" $"0.0.0.0:($reth_metrics_port)" - "--log.file.directory" $log_dir - "--faucet.enabled" - "--faucet.private-key" "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" - "--faucet.amount" "1000000000000" - "--faucet.address" "0x20c0000000000000000000000000000000000000" - "--faucet.address" "0x20c0000000000000000000000000000000000001" - ] -} - -# Build dev mode specific arguments -def build-dev-args [] { - [ - "--dev" - "--dev.block-time" "1sec" - "--builder.gaslimit" "3000000000" - "--builder.max-tasks" "8" - "--builder.deadline" "3" - ] -} - -# ============================================================================ -# Consensus mode -# ============================================================================ - -def run-consensus-nodes [nodes: int, accounts: int, genesis: string, samply: bool, samply_args: list, reset: bool, profile: string, loud: bool, extra_args: list] { - # Check if we need to generate localnet (only if no custom genesis provided) - if $genesis == "" { - let needs_generation = $reset or (not ($LOCALNET_DIR | path exists)) or ( - (ls $LOCALNET_DIR | where type == "dir" | get name | where { |d| ($d | path basename) =~ '^\d+\.\d+\.\d+\.\d+:\d+$' } | length) == 0 - ) - - if $needs_generation { - if $reset { - print "Resetting localnet data..." - } else { - print "Localnet not found, generating..." - } - rm -rf $LOCALNET_DIR - - # Generate validator addresses (port 8000, 8100, 8200, ...) - # Using 100-port gaps to avoid collisions with system services (e.g., Intuit on 8021) - let validators = (0..<$nodes | each { |i| $"127.0.0.1:($i * 100 + 8000)" } | str join ",") - - print $"Generating localnet with ($accounts) accounts and ($nodes) validators..." - cargo run -p tempo-xtask --profile $profile -- generate-localnet -o $LOCALNET_DIR --accounts $accounts --validators $validators --force | ignore - } - } - - # Parse the generated node configs - let genesis_path = if $genesis != "" { $genesis } else { $"($LOCALNET_DIR)/genesis.json" } - - # Build trusted peers from enode.identity files - let validator_dirs = (ls $LOCALNET_DIR | where type == "dir" | get name | where { |d| ($d | path basename) =~ '^\d+\.\d+\.\d+\.\d+:\d+$' }) - let trusted_peers = ($validator_dirs | each { |d| - let addr = ($d | path basename) - let port = ($addr | split row ":" | get 1 | into int) - let identity = (open $"($d)/enode.identity" | str trim) - $"enode://($identity)@127.0.0.1:($port + 1)" - } | str join ",") - - print $"Found ($validator_dirs | length) validator configs" - - let tempo_bin = if $profile == "dev" { - "./target/debug/tempo" - } else { - $"./target/($profile)/tempo" - } - - # Start background nodes first (all except node 0) - print $"Starting ($validator_dirs | length) nodes..." - print $"Logs: ($LOGS_DIR)/" - print "Press Ctrl+C to stop all nodes." - - let foreground_node = $validator_dirs | first - let background_nodes = $validator_dirs | skip 1 - - for node in $background_nodes { - run-consensus-node $node $genesis_path $trusted_peers $tempo_bin $loud false [] $extra_args true - } - - # Run node 0 in foreground (receives Ctrl+C directly) - run-consensus-node $foreground_node $genesis_path $trusted_peers $tempo_bin $loud $samply $samply_args $extra_args false -} - -# Run a single consensus node (foreground or background) -def run-consensus-node [ - node_dir: string - genesis_path: string - trusted_peers: string - tempo_bin: string - loud: bool - samply: bool - samply_args: list - extra_args: list - background: bool -] { - let addr = ($node_dir | path basename) - let port = ($addr | split row ":" | get 1 | into int) - let node_index = (port-to-node-index $port) - let http_port = 8545 + $node_index - - let log_dir = $"($LOGS_DIR)/($addr)" - mkdir $log_dir - - let args = (build-consensus-node-args $node_dir $genesis_path $trusted_peers $port $log_dir) - | append (log-filter-args $loud) - | append $extra_args - - let cmd = wrap-samply [$tempo_bin ...$args] $samply $samply_args - - print $" Node ($addr) -> http://localhost:($http_port)(if $background { '' } else { ' (foreground)' })" - - if $background { - job spawn { sh -c $"($cmd | str join ' ') 2>&1" | lines | each { |line| print $"[($addr)] ($line)" } } - } else { - print $" Running: ($cmd | str join ' ')" - run-external ($cmd | first) ...($cmd | skip 1) - } -} - -# Build full node arguments for consensus mode -def build-consensus-node-args [node_dir: string, genesis_path: string, trusted_peers: string, port: int, log_dir: string] { - let node_index = (port-to-node-index $port) - let http_port = 8545 + $node_index - let reth_metrics_port = 9001 + $node_index - - (build-base-args $genesis_path $node_dir $log_dir $http_port $reth_metrics_port) - | append (build-consensus-args $node_dir $trusted_peers $port) -} - -# Build consensus mode specific arguments -def build-consensus-args [node_dir: string, trusted_peers: string, port: int] { - let signing_key = $"($node_dir)/signing.key" - let signing_share = $"($node_dir)/signing.share" - let enode_key = $"($node_dir)/enode.key" - - let execution_p2p_port = $port + 1 - let metrics_port = $port + 2 - let authrpc_port = $port + 3 - - [ - "--consensus.signing-key" $signing_key - "--consensus.signing-share" $signing_share - "--consensus.listen-address" $"127.0.0.1:($port)" - "--consensus.metrics-address" $"127.0.0.1:($metrics_port)" - "--trusted-peers" $trusted_peers - "--port" $"($execution_p2p_port)" - "--discovery.port" $"($execution_p2p_port)" - "--p2p-secret-key" $enode_key - "--authrpc.port" $"($authrpc_port)" - "--consensus.fee-recipient" "0x0000000000000000000000000000000000000000" - ] -} - -# ============================================================================ -# Bench command -# ============================================================================ - -# Run a full benchmark: start infra, localnet, and tempo-bench -def "main bench" [ - --mode: string = "consensus" # Mode: "dev" or "consensus" - --preset: string = "" # Preset: tip20, erc20, swap, order, tempo-mix - --tps: int = 10000 # Target TPS - --duration: int = 30 # Duration in seconds - --accounts: int = 1000 # Number of accounts - --max-concurrent-requests: int = 100 # Max concurrent requests - --nodes: int = 3 # Number of consensus nodes (consensus mode only) - --genesis: string = "" # Custom genesis file path (skips generation) - --samply # Profile nodes with samply - --samply-args: string = "" # Additional samply arguments (space-separated) - --reset # Reset localnet before starting - --loud # Show node logs (silent by default) - --profile: string = $DEFAULT_PROFILE # Cargo build profile - --features: string = $DEFAULT_FEATURES # Cargo features - --node-args: string = "" # Additional node arguments (space-separated) - --bench-args: string = "" # Additional tempo-bench arguments (space-separated) -] { - validate-mode $mode - - # Validate --nodes is only used with consensus mode - if $mode == "dev" and $nodes != 3 { - print "Error: --nodes is only valid with --mode consensus" - exit 1 - } - - # Validate: either preset or bench-args must be provided - if $preset == "" and $bench_args == "" { - print "Error: either --preset or --bench-args must be provided" - print $" Available presets: ($PRESETS | columns | str join ', ')" - exit 1 - } - - # Validate preset if provided - if $preset != "" and not ($preset in $PRESETS) { - print $"Unknown preset: ($preset). Available: ($PRESETS | columns | str join ', ')" - exit 1 - } - - let weights = if $preset != "" { $PRESETS | get $preset } else { [0.0, 0.0, 0.0, 0.0] } - - # Start observability stack - print "Starting observability stack..." - docker compose -f $"($BENCH_DIR)/docker-compose.yml" up -d - - # Build both binaries first - build-tempo ["tempo" "tempo-bench"] $profile $features - - # Start nodes in background (skip build since we already compiled) - let num_nodes = if $mode == "dev" { 1 } else { $nodes } - print $"Starting ($num_nodes) ($mode) node\(s\)..." - - # Ensure at least as many accounts as validators for genesis generation (+1 for admin account) - let genesis_accounts = ([$accounts $num_nodes] | math max) + 1 - - let node_cmd = [ - "nu" "tempo.nu" "localnet" - "--mode" $mode - "--accounts" $"($genesis_accounts)" - "--skip-build" - "--force" - "--profile" $profile - "--features" $features - ] - | append (if $mode == "consensus" { ["--nodes" $"($nodes)"] } else { [] }) - | append (if $genesis != "" { ["--genesis" $genesis] } else { [] }) - | append (if $reset { ["--reset"] } else { [] }) - | append (if $samply { ["--samply"] } else { [] }) - | append (if $samply_args != "" { [$"--samply-args=\"($samply_args)\""] } else { [] }) - | append (if $loud { ["--loud"] } else { [] }) - | append (if $node_args != "" { [$"--node-args=\"($node_args)\""] } else { [] }) - - # Spawn nodes as a background job (pipe output to show logs) - let node_cmd_str = ($node_cmd | str join " ") - print $" Command: ($node_cmd_str)" - job spawn { nu -c $node_cmd_str o+e>| lines | each { |line| print $line } } - - # Wait for nodes to be ready - sleep 2sec - print "Waiting for nodes to be ready..." - let rpc_urls = (0..<$num_nodes | each { |i| $"http://localhost:(8545 + $i)" }) - for url in $rpc_urls { - wait-for-rpc $url - } - print "All nodes ready!" - - # Run tempo-bench - let tempo_bench_bin = if $profile == "dev" { - "./target/debug/tempo-bench" - } else { - $"./target/($profile)/tempo-bench" - } - let bench_cmd = [ - $tempo_bench_bin - "run-max-tps" - "--tps" $"($tps)" - "--duration" $"($duration)" - "--accounts" $"($accounts)" - "--max-concurrent-requests" $"($max_concurrent_requests)" - "--target-urls" ($rpc_urls | str join ",") - "--faucet" - "--clear-txpool" - ] - | append (if $preset != "" { - [ - "--tip20-weight" $"($weights | get 0)" - "--erc20-weight" $"($weights | get 1)" - "--swap-weight" $"($weights | get 2)" - "--place-order-weight" $"($weights | get 3)" - ] - } else { [] }) - | append (if $bench_args != "" { $bench_args | split row " " } else { [] }) - - print $"Running benchmark: ($bench_cmd | str join ' ')" - try { - bash -c $"ulimit -Sn unlimited && ($bench_cmd | str join ' ')" - } catch { - print "Benchmark interrupted or failed." - } - - # Cleanup - print "Cleaning up..." - main kill - - # Wait for samply to finish saving profiles - if $samply { - print "Waiting for samply to finish..." - loop { - let samply_running = (ps | where name =~ "samply" | length) > 0 - if not $samply_running { - break - } - sleep 500ms - } - print "Samply profiles saved." - } - - print "Done." -} - -# Wait for an RPC endpoint to be ready and chain advancing -def wait-for-rpc [url: string, max_attempts: int = 120] { - mut attempt = 0 - mut start_block: int = -1 - - loop { - $attempt = $attempt + 1 - if $attempt > $max_attempts { - print $" Timeout waiting for ($url)" - exit 1 - } - let result = (do { cast block-number --rpc-url $url } | complete) - if $result.exit_code == 0 { - let block = ($result.stdout | str trim | into int) - if $start_block == -1 { - $start_block = $block - print $" ($url) connected \(block ($block)\), waiting for chain to advance..." - } else if $block > $start_block { - print $" ($url) ready \(block ($start_block) -> ($block)\)" - break - } else { - if ($attempt mod 10) == 0 { - print $" ($url) still at block ($block)... \(($attempt)s\)" - } - } - } else { - if ($attempt mod 10) == 0 { - print $" Still waiting for ($url)... \(($attempt)s\)" - } - } - sleep 1sec - } -} - -# ============================================================================ -# Help -# ============================================================================ - -# Show help -def main [] { - print "Tempo local utilities" - print "" - print "Usage:" - print " nu tempo.nu bench [flags] Run full benchmark (infra + localnet + bench)" - print " nu tempo.nu localnet [flags] Run Tempo localnet" - print " nu tempo.nu infra up Start Grafana + Prometheus" - print " nu tempo.nu infra down Stop the observability stack" - print " nu tempo.nu kill Kill any running tempo processes" - print "" - print "Bench flags (either --preset or --bench-args required):" - print " --mode Mode: dev or consensus (default: consensus)" - print " --preset

Preset: tip20, erc20, swap, order, tempo-mix" - print " --tps Target TPS (default: 10000)" - print " --duration Duration in seconds (default: 30)" - print " --accounts Number of accounts (default: 1000)" - print " --max-concurrent-requests Max concurrent requests (default: 100)" - print " --nodes Number of consensus nodes (default: 3, consensus mode only)" - print " --samply Profile nodes with samply" - print " --samply-args Additional samply arguments (space-separated)" - print " --reset Reset localnet before starting" - print " --loud Show all node logs (WARN/ERROR shown by default)" - print $" --profile

Cargo profile \(default: ($DEFAULT_PROFILE)\)" - print $" --features Cargo features \(default: ($DEFAULT_FEATURES)\)" - print " --node-args Additional node arguments (space-separated)" - print " --bench-args Additional tempo-bench arguments (space-separated)" - print "" - print "Localnet flags:" - print " --mode Mode (default: dev)" - print " --nodes Number of validators for consensus (default: 3)" - print " --accounts Genesis accounts (default: 1000)" - print " --samply Enable samply profiling (foreground node only)" - print " --samply-args Additional samply arguments (space-separated)" - print " --loud Show all node logs (WARN/ERROR shown by default)" - print " --reset Wipe and regenerate localnet" - print $" --profile

Cargo profile \(default: ($DEFAULT_PROFILE)\)" - print $" --features Cargo features \(default: ($DEFAULT_FEATURES)\)" - print " --node-args Additional node arguments (space-separated)" - print "" - print "Examples:" - print " nu tempo.nu bench --preset tip20 --tps 20000 --duration 60" - print " nu tempo.nu bench --preset tempo-mix --tps 5000 --samply --reset" - print " nu tempo.nu infra up" - print " nu tempo.nu localnet --mode dev --samply --accounts 50000 --reset" - print " nu tempo.nu localnet --mode consensus --nodes 3" - print "" - print "Port assignments (consensus mode, per node N=0,1,2...):" - print " Consensus: 8000 + N*100" - print " P2P: 8001 + N*100" - print " Metrics: 8002 + N*100" - print " AuthRPC: 8003 + N*100" - print " HTTP RPC: 8545 + N" - print " Reth Metrics: 9001 + N" -} From 93c4e7e17fbab4b87259f50a8e1c1ad33f71bee9 Mon Sep 17 00:00:00 2001 From: Dankrad Feist Date: Mon, 20 Apr 2026 18:40:16 +0300 Subject: [PATCH 11/12] test: regenerate zone-test-genesis with Address::ZERO tempo_portal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The integration tests' start_from_l1() patches the ZoneInbox/ZoneConfig bytecode at test setup time by replacing Address::ZERO with the real L1 portal address (see crates/tempo-zone/tests/it/utils.rs — expects 4 occurrences in ZoneInbox and 1 in ZoneConfig). The previous regeneration baked 0xbb..bb as the placeholder, causing `expected 4 tempoPortal immutable(s) ... found 0` assertion failures in all start_from_l1 integration tests (demo_cross_zone, demo_shield_and_send, etc.). Regenerated with --tempo-portal 0x0000...0000 to match main's convention. Made-with: Cursor --- crates/tempo-zone/tests/assets/zone-test-genesis.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/tempo-zone/tests/assets/zone-test-genesis.json b/crates/tempo-zone/tests/assets/zone-test-genesis.json index 553a16f99..8f42a913f 100644 --- a/crates/tempo-zone/tests/assets/zone-test-genesis.json +++ b/crates/tempo-zone/tests/assets/zone-test-genesis.json @@ -41,7 +41,7 @@ "0x1c00000000000000000000000000000000000000": { "nonce": "0x1", "balance": "0x0", - "code": "0x60806040526004361015610011575f80fd5b5f3560e01c80631d04645f146101245780632245d0831461011f5780632e224dee1461011a5780633d7a27611461011557806346903867146101105780634732f8bb1461010b57806352d922a51461010657806358c3659914610101578063615cf854146100fc5780636aba6931146100f757806380a4cbc8146100f257806381e3da6b146100ed5780639a7361eb146100e8578063c334cd20146100e3578063f3b52855146100de578063f495be0b146100d95763fe770099146100d4575f80fd5b61052e565b610505565b6104dc565b6104bf565b6104a2565b610345565b610329565b6102b1565b61023a565b610214565b6101f7565b6101d1565b6101b1565b610194565b610177565b61014e565b3461014a575f36600319011261014a5760206001600160401b0360075416604051908152f35b5f80fd5b3461014a575f36600319011261014a5760206001600160401b0360015460401c16604051908152f35b3461014a575f36600319011261014a576020600454604051908152f35b3461014a575f36600319011261014a576020600954604051908152f35b3461014a575f36600319011261014a57602060075460c01c604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360085416604051908152f35b3461014a575f36600319011261014a576020600254604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360015416604051908152f35b3461014a575f36600319011261014a576003546040516001600160a01b039091168152602090f35b600435906001600160a01b038216820361014a57565b60206040818301928281528451809452019201905f5b81811061029b5750505090565b825184526020938401939092019160010161028e565b3461014a57604036600319011261014a576102ca610262565b6024356001600160401b03811161014a573660238201121561014a5780600401356001600160401b03811161014a573660248260051b8401011161014a57610325926024610319930190610655565b60405191829182610278565b0390f35b3461014a575f36600319011261014a5760205f54604051908152f35b3461014a57604036600319011261014a5761035e610262565b3360016007609a1b01141580610491575b80610480575b61041557600754604051631e7d027560e31b81526001600160a01b03909216600483015260248035908301526001600160401b0316604482015260208160648160046007609a1b015afa801561041057610325915f916103e1575b506040519081529081906020820190565b610403915060203d602011610409575b6103fb8183610742565b8101906107f6565b5f6103d0565b503d6103f1565b6107eb565b60405162461bcd60e51b815260206004820152603b60248201527f54656d706f53746174653a206f6e6c79207a6f6e652073797374656d20636f6e60448201527f7472616374732063616e20726561642054656d706f20737461746500000000006064820152608490fd5b503360036007609a1b011415610375565b503360026007609a1b01141561036f565b3461014a575f36600319011261014a576020600554604051908152f35b3461014a575f36600319011261014a576020600654604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360075460401c16604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360075460801c16604051908152f35b3461014a57602036600319011261014a576004356001600160401b03811161014a573660238201121561014a578060040135906001600160401b03821161014a57366024838301011161014a576007609a1b193301610646576105b26105ad5f54926105a26007546001600160401b031690565b946024369201610805565b6108c6565b60025403610637576001600160401b036105ec6105e06105da6007546001600160401b031690565b9361085e565b6001600160401b031690565b9116908103610628575f546004546040519081527fdd85219569c3c880f014955916f426d1ca039714b59ce33e24f151f155ac26b990602090a3005b631391e11b60e21b5f5260045ffd5b63591c836760e01b5f5260045ffd5b6303300c7360e31b5f5260045ffd5b91903360016007609a1b0114158061071d575b8061070c575b61041557600754604051632593f8c960e01b81526001600160a01b03909416600485015260606024850152606484018390526001600160401b03166001600160fb1b03831161014a578380926084925f9560051b8092858501376044830152810103018160046007609a1b015afa908115610410575f916106ed575090565b61070991503d805f833e6107018183610742565b810190610768565b90565b503360036007609a1b01141561066e565b503360026007609a1b011415610668565b634e487b7160e01b5f52604160045260245ffd5b90601f801991011681019081106001600160401b0382111761076357604052565b61072e565b60208183031261014a578051906001600160401b03821161014a57019080601f8301121561014a578151916001600160401b038311610763578260051b90604051936107b76020840186610742565b845260208085019282010192831161014a57602001905b8282106107db5750505090565b81518152602091820191016107ce565b6040513d5f823e3d90fd5b9081602091031261014a575190565b9291926001600160401b038211610763576040519161082e601f8201601f191660200184610742565b82948184528183011161014a578281602093845f960137010152565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b036001911601906001600160401b03821161087c57565b61084a565b906001820180921161087c57565b600101908160011161087c57565b906021820180921161087c57565b906015820180921161087c57565b9190820180921161087c57565b805160208201205f556108d881610c28565b80915015610ba85761098b61095a61091c836109166108fa6109939688610dd1565b6001600160401b03166001600160401b03196001541617600155565b85610ea6565b905061095461092b8287610dd1565b67ffffffffffffffff60401b6001549160401b169067ffffffffffffffff60401b191617600155565b84610ea6565b90506109856109698286610dd1565b6001600160401b03166001600160401b03196008541617600855565b83610ea6565b905082610d0e565b91908215610ba857610b77610b6f610b5b610b53610b1f610add610aa5610a74610a6c610a648b610a5e610a598f610a3c610a286109f16109e9846109e36109de610a50978b611020565b600255565b88610ea6565b905087610ea6565b9050610a22610a0082896110f0565b60018060a01b03166bffffffffffffffffffffffff60a01b6003541617600355565b86610ea6565b9050610916610a378288611020565b600455565b9050610954610a4b8287611020565b600555565b93849150611020565b600655565b8c610ea6565b90508b610ea6565b90508a610ea6565b9050610a9f610a83828c610dd1565b6001600160401b03166001600160401b03196007541617600755565b89610ea6565b90506109e3610ab4828b610dd1565b67ffffffffffffffff60401b6007549160401b169067ffffffffffffffff60401b191617600755565b9050610b19610aec828a610dd1565b6007805467ffffffffffffffff60801b191660809290921b67ffffffffffffffff60801b16919091179055565b87610ea6565b9050610a22610b2e8289610dd1565b600780546001600160c01b031660c09290921b6001600160c01b031916919091179055565b905085610ea6565b9050610954610b6a8287611020565b600955565b905083610ea6565b9050905b610b8581856108b9565b821015610ba257610b99610b859284610ea6565b90509150610b7b565b50505050565b6305787a5560e41b5f5260045ffd5b908151811015610bc8570160200190565b634e487b7160e01b5f52603260045260245ffd5b60ff60f6199116019060ff821161087c57565b60ff60bf199116019060ff821161087c57565b60ff607f199116019060ff821161087c57565b60ff60b6199116019060ff821161087c57565b805115610d0757610c53610c4d610c3f5f84610bb7565b516001600160f81b03191690565b60f81c90565b9060ff821660bf8111610c69575050505f905f90565b60f710610c8d5750610c7d610c8391610bef565b60ff1690565b906107095f610881565b9190610c7d610c9b91610bdc565b610cad81610ca85f610881565b6108b9565b835110610cff575f925f905b828210610ccf57505061070990610ca85f610881565b909360019060081b610cf6610c7d610c4d610c3f610cf08a610ca85f610881565b87610bb7565b17940190610cb9565b505f91508190565b505f905f90565b9190918051831015610cff57610d2a610c4d610c3f8584610bb7565b9060ff821660bf8111610d425750505090505f905f90565b60f710610d5f5750610d59610c7d61070992610bef565b92610881565b9290610c7d610d6d91610bdc565b90610d7b82610ca883610881565b845110610dc7575f935f905b838210610d9d57505090610ca861070992610881565b909460019060081b610dbe610c7d610c4d610c3f610cf08b610ca88a610881565b17950190610d87565b505090505f905f90565b8051821015610ba857610dea610c4d610c3f8484610bb7565b60ff81169290607f8411610dfe5750505090565b90919392608081145f14610e1457505f93505050565b60818110159081610e9a575b5015610ba857610c7d610e3291610c02565b90610e4082610ca883610881565b845110610ba85792905f935f925b828410610e5b5750505050565b90919294610e7660019167ffffffffffffff009060081b1690565b610e8f610c7d610c4d610c3f610cf08b610ca88a610881565b179501929190610e4e565b6088915011155f610e20565b9190918051831015610ba857610ec2610c4d610c3f8584610bb7565b9060ff8216607f8111610ee15750505090610edc90610881565b600191565b60b78111610f0c575050610efa610c7d61070992610c02565b610ca8610f068261088f565b94610881565b60bf8111610f78575090610c7d610f2291610c15565b5f915f905b828210610f4e57505090610ca882610ca8610f4884610ca86107099761088f565b96610881565b909260019060081b610f6f610c7d610c4d610c3f610cf089610ca88d610881565b17930190610f27565b60f710610f8f5750610efa610c7d61070992610bef565b90610c7d610f9c91610bdc565b5f915f905b828210610fc257505090610ca882610ca8610f4884610ca86107099761088f565b909260019060081b610fe3610c7d610c4d610c3f610cf089610ca88d610881565b17930190610fa1565b602003906020821161087c57565b5f1981019190821161087c57565b600381901b91906001600160fd1b0381160361087c57565b908151811015610ba85761103a610c4d610c3f8385610bb7565b60ff81169060a082036110615750506110528161089d565b825110610ba857016021015190565b909290607f84116110725750505090565b909192608081101590816110e4575b5015610ba857610c7d61109391610c02565b91826110a0575050505f90565b60208311610ba8576110b583610ca883610881565b825110610ba8576110d96110d460216001936110df9501015194610fec565b611008565b1b610ffa565b191690565b60b7915011155f611081565b908151811015610ba85760ff61110c610c4d610c3f8486610bb7565b1660948103611131575061111f816108ab565b825110610ba857016021015160601c90565b608014159150610ba89050575f9056fea2646970667358221220de5b6706c2b17c429955607698a559d3537d3785b13cf012a01a22419972e1b864736f6c634300081e0033", + "code": "0x60806040526004361015610011575f80fd5b5f3560e01c80631d04645f146101245780632245d0831461011f5780632e224dee1461011a5780633d7a27611461011557806346903867146101105780634732f8bb1461010b57806352d922a51461010657806358c3659914610101578063615cf854146100fc5780636aba6931146100f757806380a4cbc8146100f257806381e3da6b146100ed5780639a7361eb146100e8578063c334cd20146100e3578063f3b52855146100de578063f495be0b146100d95763fe770099146100d4575f80fd5b61052e565b610505565b6104dc565b6104bf565b6104a2565b610345565b610329565b6102b1565b61023a565b610214565b6101f7565b6101d1565b6101b1565b610194565b610177565b61014e565b3461014a575f36600319011261014a5760206001600160401b0360075416604051908152f35b5f80fd5b3461014a575f36600319011261014a5760206001600160401b0360015460401c16604051908152f35b3461014a575f36600319011261014a576020600454604051908152f35b3461014a575f36600319011261014a576020600954604051908152f35b3461014a575f36600319011261014a57602060075460c01c604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360085416604051908152f35b3461014a575f36600319011261014a576020600254604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360015416604051908152f35b3461014a575f36600319011261014a576003546040516001600160a01b039091168152602090f35b600435906001600160a01b038216820361014a57565b60206040818301928281528451809452019201905f5b81811061029b5750505090565b825184526020938401939092019160010161028e565b3461014a57604036600319011261014a576102ca610262565b6024356001600160401b03811161014a573660238201121561014a5780600401356001600160401b03811161014a573660248260051b8401011161014a57610325926024610319930190610655565b60405191829182610278565b0390f35b3461014a575f36600319011261014a5760205f54604051908152f35b3461014a57604036600319011261014a5761035e610262565b3360016007609a1b01141580610491575b80610480575b61041557600754604051631e7d027560e31b81526001600160a01b03909216600483015260248035908301526001600160401b0316604482015260208160648160046007609a1b015afa801561041057610325915f916103e1575b506040519081529081906020820190565b610403915060203d602011610409575b6103fb8183610742565b8101906107f6565b5f6103d0565b503d6103f1565b6107eb565b60405162461bcd60e51b815260206004820152603b60248201527f54656d706f53746174653a206f6e6c79207a6f6e652073797374656d20636f6e60448201527f7472616374732063616e20726561642054656d706f20737461746500000000006064820152608490fd5b503360036007609a1b011415610375565b503360026007609a1b01141561036f565b3461014a575f36600319011261014a576020600554604051908152f35b3461014a575f36600319011261014a576020600654604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360075460401c16604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360075460801c16604051908152f35b3461014a57602036600319011261014a576004356001600160401b03811161014a573660238201121561014a578060040135906001600160401b03821161014a57366024838301011161014a576007609a1b193301610646576105b26105ad5f54926105a26007546001600160401b031690565b946024369201610805565b6108c6565b60025403610637576001600160401b036105ec6105e06105da6007546001600160401b031690565b9361085e565b6001600160401b031690565b9116908103610628575f546004546040519081527fdd85219569c3c880f014955916f426d1ca039714b59ce33e24f151f155ac26b990602090a3005b631391e11b60e21b5f5260045ffd5b63591c836760e01b5f5260045ffd5b6303300c7360e31b5f5260045ffd5b91903360016007609a1b0114158061071d575b8061070c575b61041557600754604051632593f8c960e01b81526001600160a01b03909416600485015260606024850152606484018390526001600160401b03166001600160fb1b03831161014a578380926084925f9560051b8092858501376044830152810103018160046007609a1b015afa908115610410575f916106ed575090565b61070991503d805f833e6107018183610742565b810190610768565b90565b503360036007609a1b01141561066e565b503360026007609a1b011415610668565b634e487b7160e01b5f52604160045260245ffd5b90601f801991011681019081106001600160401b0382111761076357604052565b61072e565b60208183031261014a578051906001600160401b03821161014a57019080601f8301121561014a578151916001600160401b038311610763578260051b90604051936107b76020840186610742565b845260208085019282010192831161014a57602001905b8282106107db5750505090565b81518152602091820191016107ce565b6040513d5f823e3d90fd5b9081602091031261014a575190565b9291926001600160401b038211610763576040519161082e601f8201601f191660200184610742565b82948184528183011161014a578281602093845f960137010152565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b036001911601906001600160401b03821161087c57565b61084a565b906001820180921161087c57565b600101908160011161087c57565b906021820180921161087c57565b906015820180921161087c57565b9190820180921161087c57565b805160208201205f556108d881610c28565b80915015610ba85761098b61095a61091c836109166108fa6109939688610dd1565b6001600160401b03166001600160401b03196001541617600155565b85610ea6565b905061095461092b8287610dd1565b67ffffffffffffffff60401b6001549160401b169067ffffffffffffffff60401b191617600155565b84610ea6565b90506109856109698286610dd1565b6001600160401b03166001600160401b03196008541617600855565b83610ea6565b905082610d0e565b91908215610ba857610b77610b6f610b5b610b53610b1f610add610aa5610a74610a6c610a648b610a5e610a598f610a3c610a286109f16109e9846109e36109de610a50978b611020565b600255565b88610ea6565b905087610ea6565b9050610a22610a0082896110f0565b60018060a01b03166bffffffffffffffffffffffff60a01b6003541617600355565b86610ea6565b9050610916610a378288611020565b600455565b9050610954610a4b8287611020565b600555565b93849150611020565b600655565b8c610ea6565b90508b610ea6565b90508a610ea6565b9050610a9f610a83828c610dd1565b6001600160401b03166001600160401b03196007541617600755565b89610ea6565b90506109e3610ab4828b610dd1565b67ffffffffffffffff60401b6007549160401b169067ffffffffffffffff60401b191617600755565b9050610b19610aec828a610dd1565b6007805467ffffffffffffffff60801b191660809290921b67ffffffffffffffff60801b16919091179055565b87610ea6565b9050610a22610b2e8289610dd1565b600780546001600160c01b031660c09290921b6001600160c01b031916919091179055565b905085610ea6565b9050610954610b6a8287611020565b600955565b905083610ea6565b9050905b610b8581856108b9565b821015610ba257610b99610b859284610ea6565b90509150610b7b565b50505050565b6305787a5560e41b5f5260045ffd5b908151811015610bc8570160200190565b634e487b7160e01b5f52603260045260245ffd5b60ff60f6199116019060ff821161087c57565b60ff60bf199116019060ff821161087c57565b60ff607f199116019060ff821161087c57565b60ff60b6199116019060ff821161087c57565b805115610d0757610c53610c4d610c3f5f84610bb7565b516001600160f81b03191690565b60f81c90565b9060ff821660bf8111610c69575050505f905f90565b60f710610c8d5750610c7d610c8391610bef565b60ff1690565b906107095f610881565b9190610c7d610c9b91610bdc565b610cad81610ca85f610881565b6108b9565b835110610cff575f925f905b828210610ccf57505061070990610ca85f610881565b909360019060081b610cf6610c7d610c4d610c3f610cf08a610ca85f610881565b87610bb7565b17940190610cb9565b505f91508190565b505f905f90565b9190918051831015610cff57610d2a610c4d610c3f8584610bb7565b9060ff821660bf8111610d425750505090505f905f90565b60f710610d5f5750610d59610c7d61070992610bef565b92610881565b9290610c7d610d6d91610bdc565b90610d7b82610ca883610881565b845110610dc7575f935f905b838210610d9d57505090610ca861070992610881565b909460019060081b610dbe610c7d610c4d610c3f610cf08b610ca88a610881565b17950190610d87565b505090505f905f90565b8051821015610ba857610dea610c4d610c3f8484610bb7565b60ff81169290607f8411610dfe5750505090565b90919392608081145f14610e1457505f93505050565b60818110159081610e9a575b5015610ba857610c7d610e3291610c02565b90610e4082610ca883610881565b845110610ba85792905f935f925b828410610e5b5750505050565b90919294610e7660019167ffffffffffffff009060081b1690565b610e8f610c7d610c4d610c3f610cf08b610ca88a610881565b179501929190610e4e565b6088915011155f610e20565b9190918051831015610ba857610ec2610c4d610c3f8584610bb7565b9060ff8216607f8111610ee15750505090610edc90610881565b600191565b60b78111610f0c575050610efa610c7d61070992610c02565b610ca8610f068261088f565b94610881565b60bf8111610f78575090610c7d610f2291610c15565b5f915f905b828210610f4e57505090610ca882610ca8610f4884610ca86107099761088f565b96610881565b909260019060081b610f6f610c7d610c4d610c3f610cf089610ca88d610881565b17930190610f27565b60f710610f8f5750610efa610c7d61070992610bef565b90610c7d610f9c91610bdc565b5f915f905b828210610fc257505090610ca882610ca8610f4884610ca86107099761088f565b909260019060081b610fe3610c7d610c4d610c3f610cf089610ca88d610881565b17930190610fa1565b602003906020821161087c57565b5f1981019190821161087c57565b600381901b91906001600160fd1b0381160361087c57565b908151811015610ba85761103a610c4d610c3f8385610bb7565b60ff81169060a082036110615750506110528161089d565b825110610ba857016021015190565b909290607f84116110725750505090565b909192608081101590816110e4575b5015610ba857610c7d61109391610c02565b91826110a0575050505f90565b60208311610ba8576110b583610ca883610881565b825110610ba8576110d96110d460216001936110df9501015194610fec565b611008565b1b610ffa565b191690565b60b7915011155f611081565b908151811015610ba85760ff61110c610c4d610c3f8486610bb7565b1660948103611131575061111f816108ab565b825110610ba857016021015160601c90565b608014159150610ba89050575f9056fea264697066735822122057b3592454e545ec01075f02fbae633b4e6428716576ab0cafcfaa18082bb5d064736f6c634300081e0033", "storage": { "0x0000000000000000000000000000000000000000000000000000000000000000": "0xb049644b1d5a0ec9d785dd48f95099e0f566112084acb1ba0814112209b432a1", "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -58,17 +58,17 @@ "0x1c00000000000000000000000000000000000001": { "nonce": "0x1", "balance": "0x0", - "code": "0x60806040526004361015610011575f80fd5b5f3560e01c80631fbb25ad146100845780632d4884821461007f57806379502c551461007a57806382648c3b14610075578063a21de6d914610070578063ce11e6ab1461006b5763d01e8d3114610066575f80fd5b610244565b6101a0565b61015c565b610140565b6100fc565b6100d6565b346100c8575f3660031901126100c8577f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b03166080908152602090f35b5f80fd5b5f9103126100c857565b346100c8575f3660031901126100c85760206001600160401b0360015416604051908152f35b346100c8575f3660031901126100c8576040517f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03168152602090f35b346100c8575f3660031901126100c85760205f54604051908152f35b346100c8575f3660031901126100c8576040517f000000000000000000000000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb6001600160a01b03168152602090f35b346100c8575f3660031901126100c8576040517f0000000000000000000000001c000000000000000000000000000000000000026001600160a01b03168152602090f35b9181601f840112156100c8578235916001600160401b0383116100c8576020808501948460051b0101116100c857565b9181601f840112156100c8578235916001600160401b0383116100c85760208085019460c085020101116100c857565b346100c85760803660031901126100c8576004356001600160401b0381116100c857366023820112156100c8578060040135906001600160401b0382116100c85736602483830101116100c8576024356001600160401b0381116100c8576102b09036906004016101e4565b6044929192356001600160401b0381116100c8576102d2903690600401610214565b91606435946001600160401b0386116100c857610302966102f960249736906004016101e4565b97909601610acb565b005b634e487b7160e01b5f52604160045260245ffd5b60a081019081106001600160401b0382111761033357604052565b610304565b60c081019081106001600160401b0382111761033357604052565b90601f801991011681019081106001600160401b0382111761033357604052565b6001600160a01b038116036100c857565b908160209103126100c8575161039a81610374565b90565b6040513d5f823e3d90fd5b908060209392818452848401375f828201840152601f01601f1916010190565b91602061039a9381815201916103a8565b634e487b7160e01b5f52603260045260245ffd5b919081101561040f5760051b81013590607e19813603018212156100c8570190565b6103d9565b3561039a81610374565b903590601e19813603018212156100c857018035906001600160401b0382116100c8576020019181360383136100c857565b95939161047c9061048a9461039a99979360018060a01b03168952608060208a015260808901916103a8565b9186830360408801526103a8565b9260608185039101526103a8565b949290936104b661039a97956104c4946060895260608901916103a8565b9186830360208801526103a8565b9260408185039101526103a8565b919081101561040f5760051b81013590603e19813603018212156100c8570190565b600211156104fe57565b634e487b7160e01b5f52602160045260245ffd5b3560028110156100c85790565b359061052a82610374565b565b35906001600160801b03821682036100c857565b60ff8116036100c857565b6001600160401b03811161033357601f01601f191660200190565b35906001600160a01b0319821682036100c857565b35906001600160801b0319821682036100c857565b919060a0838203126100c857604051906105a982610318565b81938035835260208101356105bd81610540565b602084015260408101356001600160401b0381116100c857810182601f820112156100c8578035916105ee8361054b565b936105fc6040519586610353565b838552602084840101116100c8576080935f60208561063d96828997018386013783010152604086015261063260608201610566565b60608601520161057b565b910152565b6020818303126100c8578035906001600160401b0382116100c8570160c0818303126100c8576040519161067583610338565b813561068081610374565b835261068e6020830161051f565b602084015261069f6040830161052c565b6040840152606082013560608401526080820135916001600160401b0383116100c8576106d360a0926106de948301610590565b60808501520161051f565b60a082015290565b634e487b7160e01b5f52601160045260245ffd5b5f1981146107085760010190565b6106e6565b919081101561040f5760c0020190565b3561039a81610540565b519081151582036100c857565b908160209103126100c85761039a90610727565b60405190610757604083610353565b600d82526c65636965732d6165732d6b657960981b6020830152565b91906040838203126100c85782516001600160401b0381116100c857830181601f820112156100c8578051916107a88361054b565b906107b66040519283610353565b838252602084840101116100c8575f60208461039a95828096018386015e830101529301610727565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b926108399060809360209397969786526bffffffffffffffffffffffff60a01b168386015260a0604086015260a08501906107df565b83810360608501525f815201936001600160801b031916910152565b9060028210156104fe5752565b929190604090610873856001610855565b6060602086015260018060a01b03815116606086015260018060a01b0360208201511660808601526001600160801b03828201511660a0860152606081015160c086015261093c60a060808301519260c060e0890152835161012089015260ff6020850151166101408901526108f885850151836101608b01526101c08a01906107df565b60608501516bffffffffffffffffffffffff841b166101808a01526080909401516001600160801b0319166101a089015201516001600160a01b0316610100870152565b930152565b6001600160a01b0390911681526001600160801b03909116602082015260400190565b6001600160a01b0391821681526001600160801b039092166020830152909116604082015260600190565b908160c09103126100c85760a0604051916109a983610338565b80356109b481610374565b835260208101356109c481610374565b602084015260408101356109d781610374565b60408401526109e86060820161052c565b60608401526080810135608084015201356106de81610374565b610100810193929160e09190610a18825f610855565b60018060a01b03815116602083015260018060a01b03602082015116604083015260018060a01b0360408201511660608301526001600160801b036060820151166080830152608081015160a083015260a0600180821b039101511660c08201520152565b908160209103126100c8575190565b906001600160401b03809116911601906001600160401b03821161070857565b908160209103126100c857516001600160401b03811681036100c85790565b9591949392969033151580611afa575b611aeb577f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b031696873b156100c85760405163fe77009960e01b8152915f9183918291610b339190600484016103c8565b0381838b5af18015610cfb57611ad7575b505f9492945b8181106119bc575050505f54925f915f915b878310610d615750505003610d52576040516381e3da6b60e01b81527f000000000000000000000000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb6001600160a01b03166004808301919091526024820152602081604481865afa8015610cfb57610d35575b50805f55610c0b610bef6001600160401b038516610bea6001546001600160401b031690565b610a8c565b6001600160401b03166001600160401b03196001541617600155565b604051631014997960e31b815291602083600481845afa928315610cfb575f93610d00575b50602060049160405192838092631d04645f60e01b82525afa8015610cfb577fd2d2bf1e295f62cd08f0f0ab45818efeaba78b58310526f7b7e9686b8aeded1a926001600160401b03925f92610cc6575b50610cc190610c986001546001600160401b031690565b6040805198895260208901929092526001600160401b0316908701529116939081906060820190565b0390a3565b610cc1919250610ced9060203d602011610cf4575b610ce58183610353565b810190610aac565b9190610c81565b503d610cdb565b61039d565b6004919350610d26602091823d8411610d2e575b610d1e8183610353565b810190610a7d565b939150610c30565b503d610d14565b610d4d9060203d602011610d2e57610d1e8183610353565b610bc4565b6361aba18160e11b5f5260045ffd5b909194610d6f8689856104d2565b610d7881610512565b610d81816104f4565b61117957610d96816020610d9e93019061041e565b81019061098f565b90604051610dc381610db560208201948686610a02565b03601f198101835282610353565b5190209560a0820191610deb610ddf845160018060a01b031690565b6001600160a01b031690565b156110ab578051610e0690610ddf906001600160a01b031681565b604082018051909491906001600160a01b03166060840191610e2f83516001600160801b031690565b91813b156100c8578c92610e5c925f92836040518096819582946340c10f1960e01b845260048401610941565b03925af19081611097575b50610fdb575082516001600160a01b037f0000000000000000000000001c00000000000000000000000000000000000002811692911681516001600160801b031684519093906001600160a01b031690803b156100c857610ee2945f8094604051978895869485936338b8fb9760e21b855260048501610964565b03925af1958615610cfb57610fb58c947f3c1af70310b8c9d43b0a7207217f398e4a3114f1728987c40addb451399ac87c94600199610fc1575b506020870151610f7390610f6590610f5790610f49906001600160a01b031696516001600160a01b031690565b99516001600160a01b031690565b95516001600160801b031690565b91516001600160a01b031690565b906040519485948b8060a01b031698856001600160a01b03918216815291811660208301526001600160801b0390921660408201529116606082015260800190565b0390a35b019190610b5c565b80610fcf5f610fd593610353565b806100cc565b5f610f1c565b60208401516001969492935090917fd5277bc9597c7da3fab9cdbba4de6005f48b9eb7389cf2389c4ea9eea3172c2191611027906001600160a01b03165b95516001600160a01b031690565b815161108f9060809061104c906001600160a01b03165b97516001600160801b031690565b930151604080516001600160a01b0390981688526001600160801b0390941660208801529286019290925260a088901b8890039081169516939081906060820190565b0390a4610fb9565b80610fcf5f6110a593610353565b5f610e67565b80519092506110c490610ddf906001600160a01b031681565b6040830180519091906001600160a01b03169060608501916110ed83516001600160801b031690565b823b156100c857611117925f92836040518096819582946340c10f1960e01b845260048401610941565b03925af18015610cfb576001958b927fd5277bc9597c7da3fab9cdbba4de6005f48b9eb7389cf2389c4ea9eea3172c2192611165575b506020810151611027906001600160a01b0316611019565b80610fcf5f61117393610353565b5f61114d565b61118d81602061119593999499019061041e565b810190610642565b90858510156119ad576111b26111aa866106fa565b95878561070d565b606083016111c08151611bba565b916080860192602060808661124687516111df85825192015160ff1690565b958335986111ee87860161071d565b604051635f8a996960e01b8152600481019490945260ff9889166024850152604484018b905288166064840152608483015290951660a48601529101803560c48501526020013560e484015282908190610104820190565b0381731c000000000000000000000000000000000001005afa908115610cfb575f9161197f575b501561197057518251516040516bffffffffffffffffffffffff197f000000000000000000000000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb60601b166020820152603481019290925260548083019190915281525f916112e591906112d7607483610353565b6112df610748565b90611d2b565b915160608101519092906001600160a01b03191690611332611317608060408701519601516001600160801b03191690565b60405163f4a7eb1360e01b8152958694859460048601610803565b0381731c000000000000000000000000000000000001015afa8015610cfb575f915f9161194c575b5080611941575b156119395761136f90611d97565b9061137f610ddf60408501610414565b6001600160a01b0390911614908161192b575b50975b6040516113ab81610db560208201948886610862565b5190209761162b575060a0820180516113cc906001600160a01b0316610ddf565b156115c05782516113e790610ddf906001600160a01b031681565b6020840180519094919291906001600160a01b0316604082019361141285516001600160801b031690565b91813b156100c8578c9261143f925f92836040518096819582946340c10f1960e01b845260048401610941565b03925af190816115ac575b5061156c575080516001600160a01b037f0000000000000000000000001c0000000000000000000000000000000000000281169116906114a261149486516001600160801b031690565b94516001600160a01b031690565b90803b156100c8576114ce945f8094604051978895869485936338b8fb9760e21b855260048501610964565b03925af1908115610cfb5761153861152a61151c6001988e967f95705d99ac13cf82894fd274cd871942e6f301c98c186271337e8fedbbb9d7ea96611558575b50516001600160a01b031690565b92516001600160a01b031690565b94516001600160801b031690565b90611550604051928392898060a01b03169683610941565b0390a3610fb9565b80610fcf5f61156693610353565b5f61150e565b945160019592507f95705d99ac13cf82894fd274cd871942e6f301c98c186271337e8fedbbb9d7ea91906115389061152a906001600160a01b031661151c565b80610fcf5f6115ba93610353565b5f61144a565b5081516115d790610ddf906001600160a01b031681565b602083018051909391906001600160a01b031691604081019261160184516001600160801b031690565b833b156100c8576114ce935f92836040518097819582946340c10f1960e01b845260048401610941565b60a083018051919391611646906001600160a01b0316610ddf565b1561185457815161166190610ddf906001600160a01b031681565b604085019461166f86610414565b90604085019261168684516001600160801b031690565b92813b156100c8578d936116b3925f92836040518096819582946340c10f1960e01b845260048401610941565b03925af19081611840575b506117ad57505082516001600160a01b037f0000000000000000000000001c00000000000000000000000000000000000002811692911681516001600160801b031684519093906001600160a01b031690803b156100c85761173a945f8094604051978895869485936338b8fb9760e21b855260048501610964565b03925af1958615610cfb576115508c947f3c1af70310b8c9d43b0a7207217f398e4a3114f1728987c40addb451399ac87c94600199611799575b506020870151610f7390610f6590610f5790610f49906001600160a01b031696610414565b80610fcf5f6117a793610353565b5f611774565b7ffc236d1b4402e76c2b0a882db36ad3a6fb0f5b6b7edc8ae317d993f10434c436919293508461108f60606117fd61103e6114946117f7602060019e9c015160018060a01b031690565b9a610414565b604080516001600160a01b0390991689526001600160801b0390911660208901529301359286019290925260a088901b8890039081169516939081906060820190565b80610fcf5f61184e93610353565b5f6116be565b50805190929061186e90610ddf906001600160a01b031681565b90604081019161187d83610414565b91604086019261189484516001600160801b031690565b833b156100c8576118be935f92836040518097819582946340c10f1960e01b845260048401610941565b03925af1908115610cfb576001968c937ffc236d1b4402e76c2b0a882db36ad3a6fb0f5b6b7edc8ae317d993f10434c43693611917575b5061108f60606117fd61103e6114946117f7602087015160018060a01b031690565b80610fcf5f61192593610353565b5f6118f5565b90506060820135145f611392565b505f97611395565b506040815114611361565b905061196a91503d805f833e6119628183610353565b810190610773565b5f61135a565b63fb1f4a4960e01b5f5260045ffd5b6119a0915060203d81116119a6575b6119988183610353565b810190610734565b5f61126d565b503d61198e565b6351de8c1f60e01b5f5260045ffd5b6119ca8183859896986103ed565b906119d482610414565b9160208101906119e4828261041e565b909260408301936119f5858561041e565b9190976060860198611a078a8861041e565b9061083f60921b3b156100c8575f95611a3593604051998a9788976374ae5b3760e11b895260048901610450565b03818361083f60921b5af18015610cfb576001967f4ac4dcc08b0c26c3fb6b58c64c1392b7934b1ce6b0382a5986ea5c3de795e05394611a9894611ab793611ac3575b50611aa0611a8f611a8883610414565b958361041e565b9690988361041e565b93909261041e565b9290916040519687968c8060a01b03169987610498565b0390a201949294610b4a565b80610fcf5f611ad193610353565b5f611a78565b80610fcf5f611ae593610353565b5f610b44565b63bb62587160e01b5f5260045ffd5b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610cfb575f91611b5a575b506001600160a01b0316331415610adb565b611b7c915060203d602011611b82575b611b748183610353565b810190610385565b5f611b48565b503d611b6a565b908160011b918083046002149015171561070857565b906001820180921161070857565b9190820180921161070857565b611beb90611be56040516020810190611bdc81610db584906006602083019252565b51902091611b89565b90611bad565b90611c74611bf883611b9f565b6040516381e3da6b60e01b81526001600160a01b037f000000000000000000000000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb818116600484015260248301969096527f0000000000000000000000001c0000000000000000000000000000000000000016949092909190602090849081906044820190565b0381885afa928315610cfb575f93611cf8575b508215611970576040516381e3da6b60e01b81526001600160a01b03929092166004830152602482015292602090849060449082905afa928315610cfb575f93611cd4575b509160ff1690565b60ff919350611cf19060203d602011610d2e57610d1e8183610353565b9290611ccc565b611d1291935060203d602011610d2e57610d1e8183610353565b915f611c87565b805191908290602001825e015f815290565b91611d7f6001611d5961039a95611d6a9560405191602083015260208252611d54604083610353565b611de0565b926040519485916020830190611d19565b8260f81b815203601e19810185520183610353565b60405190602082015260208152611d54604082610353565b90815160408103611db357506034602083015160601c92015190565b633fbbeba160e21b5f52600452604060245260445ffd5b61039a9392604092825260208201520190611d19565b5f908051604081115f14611eec57505f611e0260209260405191828092611d19565b039060025afa15610cfb5760205f611e7d610db5611e718351965b6040519283917f363636363636363636363636363636363636363636363636363636363636363689187f36363636363636363636363636363636363636363636363636363636363636368b18898501611dca565b60405191828092611d19565b039060025afa15610cfb57611edc7f5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c611e715f93610db56020968651908560405196879518911889850191606093918352602083015260408201520190565b039060025afa15610cfb575f5190565b6020808301519490821193509160018414611f5b57505f925b60208210611f45575b6040821016611f2b575b505f611e7d610db5611e71602094611e1d565b600160409190910360031b1b5f190119909116905f611f18565b935f1960018360200360031b1b01191693611f0e565b6040015192611f0556fea26469706673582212206791853311d53751fc5de422126d7d14022ca5ff0f1562bb69b859880af8e83264736f6c634300081e0033" + "code": "0x60806040526004361015610011575f80fd5b5f3560e01c80631fbb25ad146100745780632d4884821461006f57806379502c551461006a57806382648c3b1461006557806397cac0fb146100605763a21de6d91461005b575f80fd5b61026c565b6101ac565b610130565b6100ec565b6100c6565b346100b8575f3660031901126100b8577f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b03166080908152602090f35b5f80fd5b5f9103126100b857565b346100b8575f3660031901126100b85760206001600160401b0360015416604051908152f35b346100b8575f3660031901126100b8576040517f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03168152602090f35b346100b8575f3660031901126100b85760205f54604051908152f35b9181601f840112156100b8578235916001600160401b0383116100b8576020808501948460051b0101116100b857565b9181601f840112156100b8578235916001600160401b0383116100b8576020808501948460071b0101116100b857565b346100b85760803660031901126100b8576004356001600160401b0381116100b857366023820112156100b8578060040135906001600160401b0382116100b85736602483830101116100b8576024356001600160401b0381116100b85761021890369060040161014c565b6044929192356001600160401b0381116100b85761023a90369060040161017c565b91606435946001600160401b0386116100b85761026a96610261602497369060040161014c565b979096016109d1565b005b346100b8575f3660031901126100b8576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b634e487b7160e01b5f52604160045260245ffd5b60a081019081106001600160401b038211176102df57604052565b6102b0565b90601f801991011681019081106001600160401b038211176102df57604052565b6001600160a01b038116036100b857565b908160209103126100b8575161032b81610305565b90565b6040513d5f823e3d90fd5b908060209392818452848401375f828201840152601f01601f1916010190565b91602061032b938181520191610339565b634e487b7160e01b5f52603260045260245ffd5b91908110156103a05760051b81013590607e19813603018212156100b8570190565b61036a565b3561032b81610305565b903590601e19813603018212156100b857018035906001600160401b0382116100b8576020019181360383136100b857565b95939161040d9061041b9461032b99979360018060a01b03168952608060208a01526080890191610339565b918683036040880152610339565b926060818503910152610339565b9492909361044761032b979561045594606089526060890191610339565b918683036020880152610339565b926040818503910152610339565b91908110156103a05760051b81013590603e19813603018212156100b8570190565b6002111561048f57565b634e487b7160e01b5f52602160045260245ffd5b3560028110156100b85790565b35906001600160801b03821682036100b857565b60ff8116036100b857565b6001600160401b0381116102df57601f01601f191660200190565b35906001600160a01b0319821682036100b857565b35906001600160801b0319821682036100b857565b919060a0838203126100b8576040519061052d826102c4565b8193803583526020810135610541816104c4565b602084015260408101356001600160401b0381116100b857810182601f820112156100b857803591610572836104cf565b9361058060405195866102e4565b838552602084840101116100b8576080935f6020856105c19682899701838601378301015260408601526105b6606082016104ea565b6060860152016104ff565b910152565b6020818303126100b8578035906001600160401b0382116100b8570160a0818303126100b857604051916105f9836102c4565b813561060481610305565b8352602082013561061481610305565b6020840152610625604083016104b0565b60408401526060820135606084015260808201356001600160401b0381116100b8576106519201610514565b608082015290565b634e487b7160e01b5f52601160045260245ffd5b5f19811461067b5760010190565b610659565b91908110156103a05760071b0190565b3561032b816104c4565b519081151582036100b857565b908160209103126100b85761032b9061069a565b604051906106ca6040836102e4565b600d82526c65636965732d6165732d6b657960981b6020830152565b91906040838203126100b85782516001600160401b0381116100b857830181601f820112156100b85780519161071b836104cf565b9061072960405192836102e4565b838252602084840101116100b8575f60208461032b95828096018386015e83010152930161069a565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b926107ac9060809360209397969786526bffffffffffffffffffffffff60a01b168386015260a0604086015260a0850190610752565b83810360608501525f815201936001600160801b031916910152565b90600282101561048f5752565b92919060806040916107e88660016107c8565b6060602087015260018060a01b03815116606087015260018060a01b03602082015116828701526001600160801b03838201511660a0870152606081015160c0870152015160a060e0860152805161010086015260ff6020820151166101208601526108648282015160a06101408801526101a0870190610752565b60608201516001600160a01b0319166101608701526080909101516001600160801b031916610180860152930152565b6001600160a01b0390911681526001600160801b03909116602082015260400190565b908160a09103126100b8576080604051916108d1836102c4565b80356108dc81610305565b835260208101356108ec81610305565b602084015260408101356108ff81610305565b6040840152610910606082016104b0565b60608401520135608082015290565b60c09093929193608060e0820195610937835f6107c8565b80516001600160a01b039081166020858101919091528201518116604080860191909152820151166060808501919091528101516001600160801b031682840152015160a08201520152565b908160209103126100b8575190565b906001600160401b03809116911601906001600160401b03821161067b57565b908160209103126100b857516001600160401b03811681036100b85790565b9591949392969033151580611482575b611473577f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b031696873b156100b85760405163fe77009960e01b8152915f9183918291610a39919060048401610359565b0381838b5af18015610c015761145f575b505f9492945b818110611344575050505f54925f915f915b878310610c675750505003610c58576040516381e3da6b60e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166004808301919091526024820152602081604481865afa8015610c0157610c3b575b50805f55610b11610af56001600160401b038516610af06001546001600160401b031690565b610992565b6001600160401b03166001600160401b03196001541617600155565b604051631014997960e31b815291602083600481845afa928315610c01575f93610c06575b50602060049160405192838092631d04645f60e01b82525afa8015610c01577fd2d2bf1e295f62cd08f0f0ab45818efeaba78b58310526f7b7e9686b8aeded1a926001600160401b03925f92610bcc575b50610bc790610b9e6001546001600160401b031690565b6040805198895260208901929092526001600160401b0316908701529116939081906060820190565b0390a3565b610bc7919250610bf39060203d602011610bfa575b610beb81836102e4565b8101906109b2565b9190610b87565b503d610be1565b61032e565b6004919350610c2c602091823d8411610c34575b610c2481836102e4565b810190610983565b939150610b36565b503d610c1a565b610c539060203d602011610c3457610c2481836102e4565b610aca565b6361aba18160e11b5f5260045ffd5b909194610c75868985610463565b610c7e816104a3565b610c8781610485565b610e2857610c9c816020610ca49301906103af565b8101906108b7565b90604051610cc981610cbb6020820194868661091f565b03601f1981018352826102e4565b5190208151909690610cf190610ce5906001600160a01b031681565b6001600160a01b031690565b6040830180519091906001600160a01b0316906060850191610d1a83516001600160801b031690565b823b156100b857610d44925f92836040518096819582946340c10f1960e01b845260048401610894565b03925af18015610c01576001958b927fd5277bc9597c7da3fab9cdbba4de6005f48b9eb7389cf2389c4ea9eea3172c2192610e0e575b506020810151610d9b906001600160a01b031695516001600160a01b031690565b8151610e0290608090610dbf906001600160a01b031697516001600160801b031690565b930151604080516001600160a01b0390981688526001600160801b0390941660208801529286019290925260a088901b8890039081169516939081906060820190565b0390a45b019190610a62565b80610e1c5f610e22936102e4565b806100bc565b5f610d7a565b610e3c816020610e449399949901906103af565b8101906105c6565b908585101561133557610ef696610e65610e5d8761066d565b968886610680565b6060840160406020610e778351611542565b929094608089019d8e51610e9085825192015160ff1690565b95833598610e9f878601610690565b8651635f8a996960e01b8152600481019490945260ff9889166024850152604484018b905288166064840152608483015290951660a48601529101803560c48501526020013560e484015282908190610104820190565b0381731c000000000000000000000000000000000001005afa908115610c01575f91611307575b50156112f857518951516040516bffffffffffffffffffffffff197f000000000000000000000000000000000000000000000000000000000000000060601b166020820152603481019290925260548083019190915281525f91610f959190610f876074836102e4565b610f8f6106bb565b906116b3565b98518099610fed610fd260806040610fbf60608701516bffffffffffffffffffffffff60a01b1690565b9501519d01516001600160801b03191690565b60405163f4a7eb1360e01b81529c8d94859460048601610776565b0381731c000000000000000000000000000000000001015afa978815610c01575f905f996112d1575b505f808a806112c6575b156112ba5750506110309061171f565b90915b60405161104981610cbb602082019489866107d5565b5190209861115b575050815161106990610ce5906001600160a01b031681565b602083018051909391906001600160a01b031691604081019261109384516001600160801b031690565b833b156100b8576110bd935f92836040518097819582946340c10f1960e01b845260048401610894565b03925af1908115610c015761112761111961110b6001988e967f95705d99ac13cf82894fd274cd871942e6f301c98c186271337e8fedbbb9d7ea96611147575b50516001600160a01b031690565b92516001600160a01b031690565b94516001600160801b031690565b9061113f604051928392898060a01b03169683610894565b0390a3610e06565b80610e1c5f611155936102e4565b5f6110fd565b835161117190610ce5906001600160a01b031681565b90604085019261118884516001600160801b031690565b833b156100b8575f6111b48d9582936040519485809481936340c10f1960e01b83528960048401610894565b03925af190816112a6575b506111ff57505083516111dd9150610ce5906001600160a01b031681565b6020840180519094906001600160a01b031683516001600160801b0316611093565b859392917ffc236d1b4402e76c2b0a882db36ad3a6fb0f5b6b7edc8ae317d993f10434c4369161129e61125f611251611243602060019c015160018060a01b031690565b98516001600160a01b031690565b96516001600160801b031690565b604080516001600160a01b0390981688526001600160801b03909116602088015286019290925260a088901b8890039081169516939081906060820190565b0390a4610e06565b80610e1c5f6112b4936102e4565b5f6111bf565b91509198505f98611033565b506040835114611020565b90506112f09198503d805f833e6112e881836102e4565b8101906106e6565b97905f611016565b63fb1f4a4960e01b5f5260045ffd5b611328915060203d811161132e575b61132081836102e4565b8101906106a7565b5f610f1d565b503d611316565b6351de8c1f60e01b5f5260045ffd5b61135281838598969861037e565b9061135c826103a5565b91602081019061136c82826103af565b9092604083019361137d85856103af565b919097606086019861138f8a886103af565b9061083f60921b3b156100b8575f956113bd93604051998a9788976374ae5b3760e11b8952600489016103e1565b03818361083f60921b5af18015610c01576001967f4ac4dcc08b0c26c3fb6b58c64c1392b7934b1ce6b0382a5986ea5c3de795e053946114209461143f9361144b575b50611428611417611410836103a5565b95836103af565b969098836103af565b9390926103af565b9290916040519687968c8060a01b03169987610429565b0390a201949294610a50565b80610e1c5f611459936102e4565b5f611400565b80610e1c5f61146d936102e4565b5f610a4a565b63bb62587160e01b5f5260045ffd5b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610c01575f916114e2575b506001600160a01b03163314156109e1565b611504915060203d60201161150a575b6114fc81836102e4565b810190610316565b5f6114d0565b503d6114f2565b908160011b918083046002149015171561067b57565b906001820180921161067b57565b9190820180921161067b57565b6115739061156d604051602081019061156481610cbb84906006602083019252565b51902091611511565b90611535565b906115fc61158083611527565b6040516381e3da6b60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000818116600484015260248301969096527f0000000000000000000000001c0000000000000000000000000000000000000016949092909190602090849081906044820190565b0381885afa928315610c01575f93611680575b5082156112f8576040516381e3da6b60e01b81526001600160a01b03929092166004830152602482015292602090849060449082905afa928315610c01575f9361165c575b509160ff1690565b60ff9193506116799060203d602011610c3457610c2481836102e4565b9290611654565b61169a91935060203d602011610c3457610c2481836102e4565b915f61160f565b805191908290602001825e015f815290565b9161170760016116e161032b956116f295604051916020830152602082526116dc6040836102e4565b611768565b9260405194859160208301906116a1565b8260f81b815203601e198101855201836102e4565b604051906020820152602081526116dc6040826102e4565b9081516040810361173b57506034602083015160601c92015190565b633fbbeba160e21b5f52600452604060245260445ffd5b61032b93926040928252602082015201906116a1565b5f908051604081115f1461187457505f61178a602092604051918280926116a1565b039060025afa15610c015760205f611805610cbb6117f98351965b6040519283917f363636363636363636363636363636363636363636363636363636363636363689187f36363636363636363636363636363636363636363636363636363636363636368b18898501611752565b604051918280926116a1565b039060025afa15610c01576118647f5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c6117f95f93610cbb6020968651908560405196879518911889850191606093918352602083015260408201520190565b039060025afa15610c01575f5190565b60208083015194908211935091600184146118e357505f925b602082106118cd575b60408210166118b3575b505f611805610cbb6117f96020946117a5565b600160409190910360031b1b5f190119909116905f6118a0565b935f1960018360200360031b1b01191693611896565b604001519261188d56fea26469706673582212208e93ef9bfe51376039a34783438753d575cafb9c32630db748d87afe43a51c4a64736f6c634300081e0033" }, "0x1c00000000000000000000000000000000000002": { "nonce": "0x1", "balance": "0x0", - "code": "0x60806040526004361015610011575f80fd5b5f3560e01c80632c37826e14610144578063340652721461013f578063378fa8fa1461013a57806343c3cb831461013557806348aa41081461013057806353a8d7391461012b578063545525f11461012657806379502c551461012157806379fa32891461011c5780637b9c9aa414610117578063a94cd93114610112578063b3b200aa1461010d578063b79a6c0c14610108578063bba9282e14610103578063c9b6ca9b146100fe578063ce7025e9146100f9578063d93af1d2146100f4578063e2e3ee5c146100ef5763f490ca96146100ea575f80fd5b610917565b6107cd565b6107ab565b610732565b610716565b6106ee565b610610565b610578565b6104e6565b610468565b6102ea565b610264565b610247565b61022b565b6101d1565b6101b6565b61019b565b610176565b610157565b5f91031261015357565b5f80fd5b34610153575f3660031901126101535760205f5460c01c604051908152f35b34610153575f3660031901126101535760206001600160801b035f5416604051908152f35b34610153575f36600319011261015357602060405160218152f35b34610153575f36600319011261015357602060405160718152f35b34610153575f366003190112610153575f60206040516101f08161094d565b8281520152604080516102028161094d565b6001600160401b0360015491828152602082600254169101908152835192835251166020820152f35b34610153575f3660031901126101535760206040516104008152f35b34610153575f366003190112610153576020600554604051908152f35b34610153575f366003190112610153576040517f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03168152602090f35b600435906001600160801b038216820361015357565b604435906001600160801b038216820361015357565b602435906001600160801b038216820361015357565b34610153576020366003190112610153576103036102a8565b331515806103a8575b61039957670de0b6b3a76400006001600160801b0382161161038a576103858161036b7f6f864cce5237e12ffc9a99fc6c59af17222c2bbb3457690cc8753ab16b5d715e936001600160801b03166001600160801b03195f5416175f55565b6040516001600160801b0390911681529081906020820190565b0390a1005b630d62f21160e11b5f5260045ffd5b63bb62587160e01b5f5260045ffd5b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610437575f91610408575b506001600160a01b031633141561030c565b61042a915060203d602011610430575b610422818361096d565b8101906109bf565b5f6103f6565b503d610418565b6109d7565b608435906001600160401b038216820361015357565b602435906001600160401b038216820361015357565b34610153576020366003190112610153576004356001600160401b038116810361015357610497602091610a19565b6001600160801b0360405191168152f35b6001600160a01b0381160361015357565b9181601f84011215610153578235916001600160401b038311610153576020838186019501011161015357565b346101535760e036600319011261015357600435610503816104a8565b60243590610510826104a8565b6105186102be565b9160643561052461043c565b60a43591610531836104a8565b60c435956001600160401b0387116101535761055e6105576105769836906004016104b9565b3691610a79565b946040519661056e60208961096d565b5f8852611027565b005b346101535761010036600319011261015357600435610596816104a8565b6024356105a2816104a8565b6105aa6102be565b916064356105b661043c565b9060a4356105c3816104a8565b60c4356001600160401b038111610153576105e29036906004016104b9565b93909260e435976001600160401b038911610153576106086105769936906004016104b9565b989097610ac3565b34610153576020366003190112610153576004353315158061066f575b610399576103858161065f7f4f0c4dec68e1e774843a5fc3a522ab2a832ecfc975b9ad8a5033736d9e47f09d93600555565b6040519081529081906020820190565b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610437575f916106cf575b506001600160a01b031633141561062d565b6106e8915060203d60201161043057610422818361096d565b5f6106bd565b34610153575f3660031901126101535760206001600160401b035f5460801c16604051908152f35b34610153575f36600319011261015357602060405161c3508152f35b346101535760603660031901126101535760043561074e610452565b604435916001600160401b0383116101535736602384011215610153578260040135916001600160401b038311610153573660248460051b86010111610153576107a161065f9360246107a79601610aea565b9161171e565b0390f35b34610153575f3660031901126101535760206107c5610b87565b604051908152f35b34610153576060366003190112610153576004356107ea816104a8565b6107f26102d4565b906044356107ff816104a8565b33151580610898575b610399576105769261084e61085e9261083161082261098e565b6001600160a01b039096168652565b5f6020860181905260408601526001600160a01b03166060850152565b6001600160801b03166080830152565b5f60a08201525f60c08201525f60e08201525f61010082015261087f610aaf565b61012082015261088d610aaf565b610140820152610d65565b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610437575f916108f8575b506001600160a01b0316331415610808565b610911915060203d60201161043057610422818361096d565b5f6108e6565b34610153575f366003190112610153576020604051670de0b6b3a76400008152f35b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b0382111761096857604052565b610939565b90601f801991011681019081106001600160401b0382111761096857604052565b6040519061099e6101608361096d565b565b6040519061099e6101408361096d565b6040519061099e60408361096d565b9081602091031261015357516109d4816104a8565b90565b6040513d5f823e3d90fd5b634e487b7160e01b5f52601160045260245ffd5b6001600160401b036001911601906001600160401b038211610a1457565b6109e2565b6001600160401b031661c350016001600160401b038111610a14576001600160401b036001600160801b035f54169116026001600160801b038116908103610a145790565b6001600160401b03811161096857601f01601f191660200190565b929192610a8582610a5e565b91610a93604051938461096d565b829481845281830111610153578281602093845f960137010152565b60405190610abe60208361096d565b5f8252565b97610adc610ae492939495969761099e9b993691610a79565b973691610a79565b96611027565b6001600160401b038211610968578160051b9060405192610b0e602084018561096d565b835260208301918101903682116101535780925b828410610b30575050505090565b83356001600160401b03811161015357820136601f8201121561015357602091610b61839236908481359101610a79565b815201930192610b22565b5f19810191908211610a1457565b91908203918211610a1457565b6004546003549081811015610ba2578103908111610a145790565b50505f90565b634e487b7160e01b5f52603260045260245ffd5b600354811015610bd85760035f52600960205f20910201905f90565b610ba8565b8054821015610bd8575f52600960205f20910201905f90565b634e487b7160e01b5f525f60045260245ffd5b90600182811c92168015610c37575b6020831014610c2357565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610c18565b818110610c4c575050565b5f8155600101610c41565b9190601f8111610c6657505050565b61099e925f5260205f20906020601f840160051c83019310610c90575b601f0160051c0190610c41565b9091508190610c83565b91909182516001600160401b03811161096857610cc181610cbb8454610c09565b84610c57565b6020601f8211600114610d00578190610cf19394955f92610cf5575b50508160011b915f199060031b1c19161790565b9055565b015190505f80610cdd565b601f19821690610d13845f5260205f2090565b915f5b818110610d4d57509583600195969710610d35575b505050811b019055565b01515f1960f88460031b161c191690555f8080610d2b565b9192602060018192868b015181550194019201610d16565b6003546801000000000000000081101561096857806001610d8b92016003556003610bdd565b610f1357815181546001600160a01b0319166001600160a01b0390911617815561099e916008906101409060208101516001850180546001600160a01b0319166001600160a01b039092169190911790556040810151600285015560608101516003850180546001600160a01b0319166001600160a01b03909216919091179055610e7460048501610e46610e2a60808501516001600160801b031690565b82546001600160801b0319166001600160801b03909116178255565b60a08301516001600160801b031681546001600160801b031660809190911b6001600160801b031916179055565b60c08101516005850155610ef860068501610eb9610e9c60e08501516001600160401b031690565b825467ffffffffffffffff19166001600160401b03909116178255565b6101008301516001600160a01b0316815468010000000000000000600160e01b03191660409190911b68010000000000000000600160e01b0316179055565b610f0a61012082015160078601610c9a565b01519101610c9a565b610bf6565b5f198114610a145760010190565b906001600160801b03809116911601906001600160801b038211610a1457565b90816020910312610153575190565b90816020910312610153575180151581036101535790565b6001600160401b03166001600160401b038114610a145760010190565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b6001600160a01b03918216815291811660208301526001600160801b03928316604083015292909116606082015260808101929092526001600160401b039290921660a0820152911660c082015261012060e082018190526109d493919261101891840190610f8a565b91610100818403910152610f8a565b95969092949693919360018060a01b03881615611341576104008151116113325761105182611ad3565b6005546112df575b61106283610a19565b9761106d8987610f26565b60405163868a2e9d60e01b8152979094906020896004815f60056007609a1b015af1988915610437575f996112ae575b50881561129f576040516323b872dd60e01b81523360048201523060248201526001600160801b03871660448201526001600160a01b038b16906020816064815f865af1908115610437575f91611270575b501561126157803b1561015357604051630852cd8d60e31b81526001600160801b039790971660048801525f908790602490829084905af18015610437577f348c28d1410ff29393c038fe0f1998384082e98e315624b24c04a4fa6288b9de99611242976111e392611247575b5061116561098e565b6001600160a01b038d1681529033602083015260408201526001600160a01b03891660608201526001600160801b038a1660808201526001600160801b038d1660a082015260c081018390526001600160401b03841660e08201526001600160a01b0385166101008201528561012082015286610140820152610d65565b5f5460801c6001600160401b03169a61122a6111fe8d610f6d565b5f805467ffffffffffffffff60801b191660809290921b67ffffffffffffffff60801b16919091179055565b6040519889986001600160401b03339e169c8a610fae565b0390a3565b806112555f61125b9361096d565b80610149565b5f61115c565b6312171d8360e31b5f5260045ffd5b611292915060203d602011611298575b61128a818361096d565b810190610f55565b5f6110ef565b503d611280565b632968ee7f60e21b5f5260045ffd5b6112d191995060203d6020116112d8575b6112c9818361096d565b810190610f46565b975f61109d565b503d6112bf565b600754430361131b575b60065460055481101561130c5761130261130791610f18565b600655565b611059565b63124ab48560e11b5f5260045ffd5b61132443600755565b61132d5f600655565b6112e9565b634b8a874d60e11b5f5260045ffd5b63c29f0c7160e01b5f5260045ffd5b91908201809211610a1457565b9060405191825f82549261137084610c09565b80845293600181169081156113d95750600114611395575b5061099e9250038361096d565b90505f9291925260205f20905f915b8183106113bd57505090602061099e928201015f611388565b60209193508060019154838589010152019101909184926113a4565b90506020925061099e94915060ff191682840152151560051b8201015f611388565b906114fb600861140961098e565b84546001600160a01b031681529360018101546001600160a01b031660208601526002810154604086015260038101546001600160a01b0316606086015261148b61147b6004830154611475611465826001600160801b031690565b6001600160801b031660808a0152565b60801c90565b6001600160801b031660a0870152565b600581015460c08601526114e36114d260068301546114c36114b3826001600160401b031690565b6001600160401b031660e08a0152565b60401c6001600160a01b031690565b6001600160a01b0316610100870152565b6114ef6007820161135d565b6101208601520161135d565b610140830152565b8051821015610bd85760209160051b010190565b604080825282516001600160a01b0316908201529291906020906115dc9080830151606087015260408101516001600160a01b0316608087015260608101516001600160801b031660a087015260808101516001600160801b031660c087015260a081015160e087015260c08101516001600160401b031661010087015260e08101516001600160a01b03166101208701526101206115c7610100830151610140808a0152610180890190610f8a565b910151868203603f1901610160880152610f8a565b930152565b6115eb8154610c09565b90816115f5575050565b81601f5f9311600114611606575055565b8183526020832061162291601f0160051c810190600101610c41565b808252602082209081548360011b9084198560031b1c191617905555565b90610f13576008815f61099e93555f60018201555f60028201555f60038201555f60048201555f60058201555f600682015561167e600782016115e1565b016115e1565b6003545f600355806116935750565b80600902906009820403610a145760035f527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b908101905b8181106116d6575050565b6009905f81555f60018201555f60028201555f60038201555f60048201555f60058201555f600682015561170c600782016115e1565b611718600882016115e1565b016116cb565b9092915f9333151580611a54575b610399576001600160401b03804316911603611a4557600354906117536004548093610b7a565b808411611a3d575b508051838103611a26575082611833575b5050506117a96117856117805f5460c01c90565b6109f6565b5f80546001600160c01b031660c09290921b6001600160c01b031916919091179055565b817fec4aff46c65f485f4b15e3c2edadda1d57d002995f5aa262a27c76b9a680ec1661182e6117d95f5460c01c90565b6118146117e46109b0565b8581526001600160401b038316602090910181905260018690556002805467ffffffffffffffff19169091179055565b6040516001600160401b0390911681529081906020820190565b0390a2565b5f199450916118429082611350565b91825b82811161187c5750505060045560045460035414611866575b5f808061176c565b61186e611684565b6118775f600455565b61185e565b61188581610b6c565b9561188f87610bbc565b50611899906113fb565b6118a38589610b7a565b6118ad9085611503565b5180610140830151906118bf91611b48565b8151602080840151604080860151905160609290921b6bffffffffffffffffffffffff191692820192835260348083019190915281526001600160a01b03909216939161190d60548261096d565b51902060608201519091906001600160a01b031660808201516001600160801b031660a08301516001600160801b031660c08401519160e0850151611958906001600160401b031690565b6101008601519094906001600160a01b0316956101200151966119796109a0565b6001600160a01b03909a168a5260208a01526001600160a01b031660408901526001600160801b031660608801526001600160801b0316608087015260a08601526001600160401b031660c08501526001600160a01b031660e0840152610100830152610120820152604051809160208201936119f69185611517565b03601f1981018252611a08908261096d565b51902095611a1590610bbc565b611a1e91611640565b5f1901611845565b630db2128560e11b5f52600452602483905260445ffd5b92505f61175b565b631391e11b60e21b5f5260045ffd5b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610437575f91611ab4575b506001600160a01b031633141561172c565b611acd915060203d60201161043057610422818361096d565b5f611aa2565b80518015611b4457602103611b2657805115610bd85760208101516001600160f81b031916600160f91b8114159081611b35575b50611b2657611b1c6021611b20920151611bca565b1590565b611b2657565b6361d0136b60e11b5f5260045ffd5b600360f81b141590505f611b07565b5050565b51611b71575f905b51818103611b5c575050565b63521a2d4d60e11b5f5260045260245260445ffd5b607190611b50565b3d15611ba3573d90611b8a82610a5e565b91611b98604051938461096d565b82523d5f602084013e565b606090565b602081519101519060208110611bbc575090565b5f199060200360031b1b1690565b80158015611c88575b611c77575f8091604051611c4d81611c3f602082019460076401000003d019916401000003d019906401000003d019818009090860208087528087018190526040870152606086015263800001e9600160ff1b0360808601526401000003d01960a086015260c0850190565b03601f19810183528261096d565b519060055afa611c5b611b79565b90158015611c7c575b611c7757611c73600191611ba8565b1490565b505f90565b50602081511415611c64565b506401000003d019811015611bd356fea2646970667358221220eb80a77022ec23ed3e41592432773382bd8fc97d603a9b06567317d40465ff5064736f6c634300081e0033" + "code": "0x60806040526004361015610011575f80fd5b5f3560e01c80632c37826e14610134578063340652721461012f578063378fa8fa1461012a57806343c3cb831461012557806348aa41081461012057806353a8d7391461011b578063545525f11461011657806379502c551461011157806379fa32891461010c5780637b9c9aa414610107578063a94cd93114610102578063b3b200aa146100fd578063b79a6c0c146100f8578063bba9282e146100f3578063c9b6ca9b146100ee578063ce7025e9146100e9578063d93af1d2146100e45763f490ca96146100df575f80fd5b6107a7565b610785565b61070c565b6106f0565b6106c8565b6105ea565b610552565b6104c0565b610442565b6102c4565b610254565b610237565b61021b565b6101c1565b6101a6565b61018b565b610166565b610147565b5f91031261014357565b5f80fd5b34610143575f3660031901126101435760205f5460c01c604051908152f35b34610143575f3660031901126101435760206001600160801b035f5416604051908152f35b34610143575f36600319011261014357602060405160218152f35b34610143575f36600319011261014357602060405160718152f35b34610143575f366003190112610143575f60206040516101e0816107dd565b8281520152604080516101f2816107dd565b6001600160401b0360015491828152602082600254169101908152835192835251166020820152f35b34610143575f3660031901126101435760206040516104008152f35b34610143575f366003190112610143576020600554604051908152f35b34610143575f366003190112610143576040517f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03168152602090f35b600435906001600160801b038216820361014357565b604435906001600160801b038216820361014357565b34610143576020366003190112610143576102dd610298565b33151580610382575b61037357670de0b6b3a76400006001600160801b038216116103645761035f816103457f6f864cce5237e12ffc9a99fc6c59af17222c2bbb3457690cc8753ab16b5d715e936001600160801b03166001600160801b03195f5416175f55565b6040516001600160801b0390911681529081906020820190565b0390a1005b630d62f21160e11b5f5260045ffd5b63bb62587160e01b5f5260045ffd5b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610411575f916103e2575b506001600160a01b03163314156102e6565b610404915060203d60201161040a575b6103fc81836107fd565b81019061084f565b5f6103d0565b503d6103f2565b610867565b608435906001600160401b038216820361014357565b602435906001600160401b038216820361014357565b34610143576020366003190112610143576004356001600160401b0381168103610143576104716020916108a9565b6001600160801b0360405191168152f35b6001600160a01b0381160361014357565b9181601f84011215610143578235916001600160401b038311610143576020838186019501011161014357565b346101435760e0366003190112610143576004356104dd81610482565b602435906104ea82610482565b6104f26102ae565b916064356104fe610416565b60a4359161050b83610482565b60c435956001600160401b03871161014357610538610531610550983690600401610493565b3691610909565b94604051966105486020896107fd565b5f8852610ea3565b005b34610143576101003660031901126101435760043561057081610482565b60243561057c81610482565b6105846102ae565b91606435610590610416565b9060a43561059d81610482565b60c4356001600160401b038111610143576105bc903690600401610493565b93909260e435976001600160401b038911610143576105e2610550993690600401610493565b98909761093f565b346101435760203660031901126101435760043533151580610649575b6103735761035f816106397f4f0c4dec68e1e774843a5fc3a522ab2a832ecfc975b9ad8a5033736d9e47f09d93600555565b6040519081529081906020820190565b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610411575f916106a9575b506001600160a01b0316331415610607565b6106c2915060203d60201161040a576103fc81836107fd565b5f610697565b34610143575f3660031901126101435760206001600160401b035f5460801c16604051908152f35b34610143575f36600319011261014357602060405161c3508152f35b346101435760603660031901126101435760043561072861042c565b604435916001600160401b0383116101435736602384011215610143578260040135916001600160401b038311610143573660248460051b860101116101435761077b6106399360246107819601610966565b9161159a565b0390f35b34610143575f36600319011261014357602061079f610a03565b604051908152f35b34610143575f366003190112610143576020604051670de0b6b3a76400008152f35b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b038211176107f857604052565b6107c9565b90601f801991011681019081106001600160401b038211176107f857604052565b6040519061082e610160836107fd565b565b6040519061082e610140836107fd565b6040519061082e6040836107fd565b90816020910312610143575161086481610482565b90565b6040513d5f823e3d90fd5b634e487b7160e01b5f52601160045260245ffd5b6001600160401b036001911601906001600160401b0382116108a457565b610872565b6001600160401b031661c350016001600160401b0381116108a4576001600160401b036001600160801b035f54169116026001600160801b0381169081036108a45790565b6001600160401b0381116107f857601f01601f191660200190565b929192610915826108ee565b9161092360405193846107fd565b829481845281830111610143578281602093845f960137010152565b9761095861096092939495969761082e9b993691610909565b973691610909565b96610ea3565b6001600160401b0382116107f8578160051b906040519261098a60208401856107fd565b835260208301918101903682116101435780925b8284106109ac575050505090565b83356001600160401b03811161014357820136601f82011215610143576020916109dd839236908481359101610909565b81520193019261099e565b5f198101919082116108a457565b919082039182116108a457565b6004546003549081811015610a1e5781039081116108a45790565b50505f90565b5f1981146108a45760010190565b906001600160801b03809116911601906001600160801b0382116108a457565b90816020910312610143575190565b90816020910312610143575180151581036101435790565b634e487b7160e01b5f52603260045260245ffd5b600354811015610aa95760035f52600960205f20910201905f90565b610a79565b8054821015610aa9575f52600960205f20910201905f90565b634e487b7160e01b5f525f60045260245ffd5b90600182811c92168015610b08575b6020831014610af457565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610ae9565b818110610b1d575050565b5f8155600101610b12565b9190601f8111610b3757505050565b61082e925f5260205f20906020601f840160051c83019310610b61575b601f0160051c0190610b12565b9091508190610b54565b91909182516001600160401b0381116107f857610b9281610b8c8454610ada565b84610b28565b6020601f8211600114610bd1578190610bc29394955f92610bc6575b50508160011b915f199060031b1c19161790565b9055565b015190505f80610bae565b601f19821690610be4845f5260205f2090565b915f5b818110610c1e57509583600195969710610c06575b505050811b019055565b01515f1960f88460031b161c191690555f8080610bfc565b9192602060018192868b015181550194019201610be7565b600354680100000000000000008110156107f857806001610c5c92016003556003610aae565b610de457815181546001600160a01b0319166001600160a01b0390911617815561082e916008906101409060208101516001850180546001600160a01b0319166001600160a01b039092169190911790556040810151600285015560608101516003850180546001600160a01b0319166001600160a01b03909216919091179055610d4560048501610d17610cfb60808501516001600160801b031690565b82546001600160801b0319166001600160801b03909116178255565b60a08301516001600160801b031681546001600160801b031660809190911b6001600160801b031916179055565b60c08101516005850155610dc960068501610d8a610d6d60e08501516001600160401b031690565b825467ffffffffffffffff19166001600160401b03909116178255565b6101008301516001600160a01b0316815468010000000000000000600160e01b03191660409190911b68010000000000000000600160e01b0316179055565b610ddb61012082015160078601610b6b565b01519101610b6b565b610ac7565b6001600160401b03166001600160401b0381146108a45760010190565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b6001600160a01b03918216815291811660208301526001600160801b03928316604083015292909116606082015260808101929092526001600160401b039290921660a0820152911660c082015261012060e08201819052610864939192610e9491840190610e06565b91610100818403910152610e06565b95969092949693919360018060a01b038816156111bd576104008151116111ae57610ecd8261194f565b60055461115b575b610ede836108a9565b97610ee98987610a32565b60405163868a2e9d60e01b8152979094906020896004815f60056007609a1b015af1988915610411575f9961112a575b50881561111b576040516323b872dd60e01b81523360048201523060248201526001600160801b03871660448201526001600160a01b038b16906020816064815f865af1908115610411575f916110ec575b50156110dd57803b1561014357604051630852cd8d60e31b81526001600160801b039790971660048801525f908790602490829084905af18015610411577f348c28d1410ff29393c038fe0f1998384082e98e315624b24c04a4fa6288b9de996110be9761105f926110c3575b50610fe161081e565b6001600160a01b038d1681529033602083015260408201526001600160a01b03891660608201526001600160801b038a1660808201526001600160801b038d1660a082015260c081018390526001600160401b03841660e08201526001600160a01b0385166101008201528561012082015286610140820152610c36565b5f5460801c6001600160401b03169a6110a661107a8d610de9565b5f805467ffffffffffffffff60801b191660809290921b67ffffffffffffffff60801b16919091179055565b6040519889986001600160401b03339e169c8a610e2a565b0390a3565b806110d15f6110d7936107fd565b80610139565b5f610fd8565b6312171d8360e31b5f5260045ffd5b61110e915060203d602011611114575b61110681836107fd565b810190610a61565b5f610f6b565b503d6110fc565b632968ee7f60e21b5f5260045ffd5b61114d91995060203d602011611154575b61114581836107fd565b810190610a52565b975f610f19565b503d61113b565b6007544303611197575b6006546005548110156111885761117e61118391610a24565b600655565b610ed5565b63124ab48560e11b5f5260045ffd5b6111a043600755565b6111a95f600655565b611165565b634b8a874d60e11b5f5260045ffd5b63c29f0c7160e01b5f5260045ffd5b919082018092116108a457565b9060405191825f8254926111ec84610ada565b80845293600181169081156112555750600114611211575b5061082e925003836107fd565b90505f9291925260205f20905f915b81831061123957505090602061082e928201015f611204565b6020919350806001915483858901015201910190918492611220565b90506020925061082e94915060ff191682840152151560051b8201015f611204565b90611377600861128561081e565b84546001600160a01b031681529360018101546001600160a01b031660208601526002810154604086015260038101546001600160a01b031660608601526113076112f760048301546112f16112e1826001600160801b031690565b6001600160801b031660808a0152565b60801c90565b6001600160801b031660a0870152565b600581015460c086015261135f61134e600683015461133f61132f826001600160401b031690565b6001600160401b031660e08a0152565b60401c6001600160a01b031690565b6001600160a01b0316610100870152565b61136b600782016111d9565b610120860152016111d9565b610140830152565b8051821015610aa95760209160051b010190565b604080825282516001600160a01b0316908201529291906020906114589080830151606087015260408101516001600160a01b0316608087015260608101516001600160801b031660a087015260808101516001600160801b031660c087015260a081015160e087015260c08101516001600160401b031661010087015260e08101516001600160a01b0316610120870152610120611443610100830151610140808a0152610180890190610e06565b910151868203603f1901610160880152610e06565b930152565b6114678154610ada565b9081611471575050565b81601f5f9311600114611482575055565b8183526020832061149e91601f0160051c810190600101610b12565b808252602082209081548360011b9084198560031b1c191617905555565b90610de4576008815f61082e93555f60018201555f60028201555f60038201555f60048201555f60058201555f60068201556114fa6007820161145d565b0161145d565b6003545f6003558061150f5750565b806009029060098204036108a45760035f527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b908101905b818110611552575050565b6009905f81555f60018201555f60028201555f60038201555f60048201555f60058201555f60068201556115886007820161145d565b6115946008820161145d565b01611547565b9092915f93331515806118d0575b610373576001600160401b038043169116036118c157600354906115cf60045480936109f6565b8084116118b9575b5080518381036118a25750826116af575b5050506116256116016115fc5f5460c01c90565b610886565b5f80546001600160c01b031660c09290921b6001600160c01b031916919091179055565b817fec4aff46c65f485f4b15e3c2edadda1d57d002995f5aa262a27c76b9a680ec166116aa6116555f5460c01c90565b611690611660610840565b8581526001600160401b038316602090910181905260018690556002805467ffffffffffffffff19169091179055565b6040516001600160401b0390911681529081906020820190565b0390a2565b5f199450916116be90826111cc565b91825b8281116116f857505050600455600454600354146116e2575b5f80806115e8565b6116ea611500565b6116f35f600455565b6116da565b611701816109e8565b9561170b87610a8d565b5061171590611277565b61171f85896109f6565b611729908561137f565b51806101408301519061173b916119c4565b8151602080840151604080860151905160609290921b6bffffffffffffffffffffffff191692820192835260348083019190915281526001600160a01b0390921693916117896054826107fd565b51902060608201519091906001600160a01b031660808201516001600160801b031660a08301516001600160801b031660c08401519160e08501516117d4906001600160401b031690565b6101008601519094906001600160a01b0316956101200151966117f5610830565b6001600160a01b03909a168a5260208a01526001600160a01b031660408901526001600160801b031660608801526001600160801b0316608087015260a08601526001600160401b031660c08501526001600160a01b031660e0840152610100830152610120820152604051809160208201936118729185611393565b03601f198101825261188490826107fd565b5190209561189190610a8d565b61189a916114bc565b5f19016116c1565b630db2128560e11b5f52600452602483905260445ffd5b92505f6115d7565b631391e11b60e21b5f5260045ffd5b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610411575f91611930575b506001600160a01b03163314156115a8565b611949915060203d60201161040a576103fc81836107fd565b5f61191e565b805180156119c0576021036119a257805115610aa95760208101516001600160f81b031916600160f91b81141590816119b1575b506119a257611998602161199c920151611a46565b1590565b6119a257565b6361d0136b60e11b5f5260045ffd5b600360f81b141590505f611983565b5050565b516119ed575f905b518181036119d8575050565b63521a2d4d60e11b5f5260045260245260445ffd5b6071906119cc565b3d15611a1f573d90611a06826108ee565b91611a1460405193846107fd565b82523d5f602084013e565b606090565b602081519101519060208110611a38575090565b5f199060200360031b1b1690565b80158015611b04575b611af3575f8091604051611ac981611abb602082019460076401000003d019916401000003d019906401000003d019818009090860208087528087018190526040870152606086015263800001e9600160ff1b0360808601526401000003d01960a086015260c0850190565b03601f1981018352826107fd565b519060055afa611ad76119f5565b90158015611af8575b611af357611aef600191611a24565b1490565b505f90565b50602081511415611ae0565b506401000003d019811015611a4f56fea2646970667358221220c507a58923eeb01609f13c1e26604cbb46eaf7befa4f49f7c8ce5aca93e940d264736f6c634300081e0033" }, "0x1c00000000000000000000000000000000000003": { "nonce": "0x1", "balance": "0x0", - "code": "0x6080806040526004361015610012575f80fd5b5f3560e01c9081631beb1ab814610561575080631fbb25ad1461051d5780633488ce0d146102dd5780635c1bba381461023b5780636d46e98714610193578063a21de6d91461014f5763e202d99514610069575f80fd5b34610138575f366003190112610138576040516381e3da6b60e01b81526001600160a01b037f000000000000000000000000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb8116600483015260016024830152602090829060449082907f0000000000000000000000001c00000000000000000000000000000000000000165afa8015610144575f9061010d575b6040516001600160a01b039091168152602090f35b506020813d60201161013c575b816101276020938361067c565b8101031261013857602090516100f8565b5f80fd5b3d915061011a565b6040513d5f823e3d90fd5b34610138575f366003190112610138576040517f000000000000000000000000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb6001600160a01b03168152602090f35b34610138576020366003190112610138576004356001600160a01b0381169081900361013857604051630b83774760e31b8152602081600481305afa908115610144575f916101f6575b506040516001600160a01b039091169091148152602090f35b90506020813d602011610233575b816102116020938361067c565b810103126101385751906001600160a01b0382168203610138579060206101dd565b3d9150610204565b34610138575f366003190112610138576040516381e3da6b60e01b81526001600160a01b037f000000000000000000000000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb811660048301525f6024830152602090829060449082907f0000000000000000000000001c00000000000000000000000000000000000000165afa8015610144575f9061010d576040516001600160a01b039091168152602090f35b34610138575f366003190112610138576040516381e3da6b60e01b81527f000000000000000000000000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb6001600160a01b038181166004840152600660248401527f0000000000000000000000001c00000000000000000000000000000000000000169190602082604481865afa918215610144575f926104e9575b5081156104da576040516020810190600682526020815261038f60408261067c565b519020915f1981019081116104c6578060011b90808204600214901517156104c65782018092116104c65760018201908183116104c6576040516381e3da6b60e01b81526001600160a01b03821660048201526024810193909352602083604481875afa928315610144575f9361048e575b506040516381e3da6b60e01b81526001600160a01b03909116600482015260248101919091529160209083908180604481015b03915afa918215610144575f92610459575b5060ff6040928351928352166020820152f35b91506020823d602011610486575b816104746020938361067c565b810103126101385790519060ff610446565b3d9150610467565b919092506020823d6020116104be575b816104ab6020938361067c565b8101031261013857905191610434610401565b3d915061049e565b634e487b7160e01b5f52601160045260245ffd5b630c322fb560e31b5f5260045ffd5b9091506020813d602011610515575b816105056020938361067c565b810103126101385751908361036d565b3d91506104f8565b34610138575f366003190112610138576040517f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b03168152602090f35b34610138576020366003190112610138576004356001600160a01b0381169190829003610138576105fe9181602080930191825260076040820152604081526105ab60608261067c565b5190206040516381e3da6b60e01b81526001600160a01b037f000000000000000000000000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb166004820152602481019190915291829081906044820190565b03817f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b03165afa8015610144575f90610649575b60209060ff604051911615158152f35b506020813d602011610674575b816106636020938361067c565b810103126101385760209051610639565b3d9150610656565b90601f8019910116810190811067ffffffffffffffff82111761069e57604052565b634e487b7160e01b5f52604160045260245ffdfea26469706673582212201c909c199411f678d91cc09085bac7c80d3458f7269a4687d397f586482f06e964736f6c634300081e0033" + "code": "0x6080806040526004361015610012575f80fd5b5f3560e01c9081631beb1ab814610561575080631fbb25ad1461051d5780633488ce0d146102dd5780635c1bba381461023b5780636d46e98714610193578063a21de6d91461014f5763e202d99514610069575f80fd5b34610138575f366003190112610138576040516381e3da6b60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260016024830152602090829060449082907f0000000000000000000000001c00000000000000000000000000000000000000165afa8015610144575f9061010d575b6040516001600160a01b039091168152602090f35b506020813d60201161013c575b816101276020938361067c565b8101031261013857602090516100f8565b5f80fd5b3d915061011a565b6040513d5f823e3d90fd5b34610138575f366003190112610138576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610138576020366003190112610138576004356001600160a01b0381169081900361013857604051630b83774760e31b8152602081600481305afa908115610144575f916101f6575b506040516001600160a01b039091169091148152602090f35b90506020813d602011610233575b816102116020938361067c565b810103126101385751906001600160a01b0382168203610138579060206101dd565b3d9150610204565b34610138575f366003190112610138576040516381e3da6b60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301525f6024830152602090829060449082907f0000000000000000000000001c00000000000000000000000000000000000000165afa8015610144575f9061010d576040516001600160a01b039091168152602090f35b34610138575f366003190112610138576040516381e3da6b60e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b038181166004840152600660248401527f0000000000000000000000001c00000000000000000000000000000000000000169190602082604481865afa918215610144575f926104e9575b5081156104da576040516020810190600682526020815261038f60408261067c565b519020915f1981019081116104c6578060011b90808204600214901517156104c65782018092116104c65760018201908183116104c6576040516381e3da6b60e01b81526001600160a01b03821660048201526024810193909352602083604481875afa928315610144575f9361048e575b506040516381e3da6b60e01b81526001600160a01b03909116600482015260248101919091529160209083908180604481015b03915afa918215610144575f92610459575b5060ff6040928351928352166020820152f35b91506020823d602011610486575b816104746020938361067c565b810103126101385790519060ff610446565b3d9150610467565b919092506020823d6020116104be575b816104ab6020938361067c565b8101031261013857905191610434610401565b3d915061049e565b634e487b7160e01b5f52601160045260245ffd5b630c322fb560e31b5f5260045ffd5b9091506020813d602011610515575b816105056020938361067c565b810103126101385751908361036d565b3d91506104f8565b34610138575f366003190112610138576040517f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b03168152602090f35b34610138576020366003190112610138576004356001600160a01b0381169190829003610138576105fe9181602080930191825260076040820152604081526105ab60608261067c565b5190206040516381e3da6b60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166004820152602481019190915291829081906044820190565b03817f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b03165afa8015610144575f90610649575b60209060ff604051911615158152f35b506020813d602011610674575b816106636020938361067c565b810103126101385760209051610639565b3d9150610656565b90601f8019910116810190811067ffffffffffffffff82111761069e57604052565b634e487b7160e01b5f52604160045260245ffdfea26469706673582212202123abc3d91c41a1be59b6f06bfc92259b93aa367f581f04eda761e4ed25c63c64736f6c634300081e0033" }, "0x1c00000000000000000000000000000000000004": { "nonce": "0x1", From ff503979833627e46048b677c1bc8212f293abbb Mon Sep 17 00:00:00 2001 From: Dankrad Feist Date: Mon, 20 Apr 2026 19:32:55 +0300 Subject: [PATCH 12/12] test: regenerate zone-test-genesis with current Solidity artifacts Previous regeneration used stale solidity artifacts that produced a ZoneInbox missing the advanceTempo selector (d01e8d31). This caused the system tx to revert at 188 gas (no matching dispatcher branch). The new genesis deploys ZoneInbox at 8091 bytes with all 7 expected function selectors including d01e8d31 advanceTempo. Made-with: Cursor --- crates/tempo-zone/tests/assets/zone-test-genesis.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/tempo-zone/tests/assets/zone-test-genesis.json b/crates/tempo-zone/tests/assets/zone-test-genesis.json index 8f42a913f..92090a151 100644 --- a/crates/tempo-zone/tests/assets/zone-test-genesis.json +++ b/crates/tempo-zone/tests/assets/zone-test-genesis.json @@ -41,7 +41,7 @@ "0x1c00000000000000000000000000000000000000": { "nonce": "0x1", "balance": "0x0", - "code": "0x60806040526004361015610011575f80fd5b5f3560e01c80631d04645f146101245780632245d0831461011f5780632e224dee1461011a5780633d7a27611461011557806346903867146101105780634732f8bb1461010b57806352d922a51461010657806358c3659914610101578063615cf854146100fc5780636aba6931146100f757806380a4cbc8146100f257806381e3da6b146100ed5780639a7361eb146100e8578063c334cd20146100e3578063f3b52855146100de578063f495be0b146100d95763fe770099146100d4575f80fd5b61052e565b610505565b6104dc565b6104bf565b6104a2565b610345565b610329565b6102b1565b61023a565b610214565b6101f7565b6101d1565b6101b1565b610194565b610177565b61014e565b3461014a575f36600319011261014a5760206001600160401b0360075416604051908152f35b5f80fd5b3461014a575f36600319011261014a5760206001600160401b0360015460401c16604051908152f35b3461014a575f36600319011261014a576020600454604051908152f35b3461014a575f36600319011261014a576020600954604051908152f35b3461014a575f36600319011261014a57602060075460c01c604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360085416604051908152f35b3461014a575f36600319011261014a576020600254604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360015416604051908152f35b3461014a575f36600319011261014a576003546040516001600160a01b039091168152602090f35b600435906001600160a01b038216820361014a57565b60206040818301928281528451809452019201905f5b81811061029b5750505090565b825184526020938401939092019160010161028e565b3461014a57604036600319011261014a576102ca610262565b6024356001600160401b03811161014a573660238201121561014a5780600401356001600160401b03811161014a573660248260051b8401011161014a57610325926024610319930190610655565b60405191829182610278565b0390f35b3461014a575f36600319011261014a5760205f54604051908152f35b3461014a57604036600319011261014a5761035e610262565b3360016007609a1b01141580610491575b80610480575b61041557600754604051631e7d027560e31b81526001600160a01b03909216600483015260248035908301526001600160401b0316604482015260208160648160046007609a1b015afa801561041057610325915f916103e1575b506040519081529081906020820190565b610403915060203d602011610409575b6103fb8183610742565b8101906107f6565b5f6103d0565b503d6103f1565b6107eb565b60405162461bcd60e51b815260206004820152603b60248201527f54656d706f53746174653a206f6e6c79207a6f6e652073797374656d20636f6e60448201527f7472616374732063616e20726561642054656d706f20737461746500000000006064820152608490fd5b503360036007609a1b011415610375565b503360026007609a1b01141561036f565b3461014a575f36600319011261014a576020600554604051908152f35b3461014a575f36600319011261014a576020600654604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360075460401c16604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360075460801c16604051908152f35b3461014a57602036600319011261014a576004356001600160401b03811161014a573660238201121561014a578060040135906001600160401b03821161014a57366024838301011161014a576007609a1b193301610646576105b26105ad5f54926105a26007546001600160401b031690565b946024369201610805565b6108c6565b60025403610637576001600160401b036105ec6105e06105da6007546001600160401b031690565b9361085e565b6001600160401b031690565b9116908103610628575f546004546040519081527fdd85219569c3c880f014955916f426d1ca039714b59ce33e24f151f155ac26b990602090a3005b631391e11b60e21b5f5260045ffd5b63591c836760e01b5f5260045ffd5b6303300c7360e31b5f5260045ffd5b91903360016007609a1b0114158061071d575b8061070c575b61041557600754604051632593f8c960e01b81526001600160a01b03909416600485015260606024850152606484018390526001600160401b03166001600160fb1b03831161014a578380926084925f9560051b8092858501376044830152810103018160046007609a1b015afa908115610410575f916106ed575090565b61070991503d805f833e6107018183610742565b810190610768565b90565b503360036007609a1b01141561066e565b503360026007609a1b011415610668565b634e487b7160e01b5f52604160045260245ffd5b90601f801991011681019081106001600160401b0382111761076357604052565b61072e565b60208183031261014a578051906001600160401b03821161014a57019080601f8301121561014a578151916001600160401b038311610763578260051b90604051936107b76020840186610742565b845260208085019282010192831161014a57602001905b8282106107db5750505090565b81518152602091820191016107ce565b6040513d5f823e3d90fd5b9081602091031261014a575190565b9291926001600160401b038211610763576040519161082e601f8201601f191660200184610742565b82948184528183011161014a578281602093845f960137010152565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b036001911601906001600160401b03821161087c57565b61084a565b906001820180921161087c57565b600101908160011161087c57565b906021820180921161087c57565b906015820180921161087c57565b9190820180921161087c57565b805160208201205f556108d881610c28565b80915015610ba85761098b61095a61091c836109166108fa6109939688610dd1565b6001600160401b03166001600160401b03196001541617600155565b85610ea6565b905061095461092b8287610dd1565b67ffffffffffffffff60401b6001549160401b169067ffffffffffffffff60401b191617600155565b84610ea6565b90506109856109698286610dd1565b6001600160401b03166001600160401b03196008541617600855565b83610ea6565b905082610d0e565b91908215610ba857610b77610b6f610b5b610b53610b1f610add610aa5610a74610a6c610a648b610a5e610a598f610a3c610a286109f16109e9846109e36109de610a50978b611020565b600255565b88610ea6565b905087610ea6565b9050610a22610a0082896110f0565b60018060a01b03166bffffffffffffffffffffffff60a01b6003541617600355565b86610ea6565b9050610916610a378288611020565b600455565b9050610954610a4b8287611020565b600555565b93849150611020565b600655565b8c610ea6565b90508b610ea6565b90508a610ea6565b9050610a9f610a83828c610dd1565b6001600160401b03166001600160401b03196007541617600755565b89610ea6565b90506109e3610ab4828b610dd1565b67ffffffffffffffff60401b6007549160401b169067ffffffffffffffff60401b191617600755565b9050610b19610aec828a610dd1565b6007805467ffffffffffffffff60801b191660809290921b67ffffffffffffffff60801b16919091179055565b87610ea6565b9050610a22610b2e8289610dd1565b600780546001600160c01b031660c09290921b6001600160c01b031916919091179055565b905085610ea6565b9050610954610b6a8287611020565b600955565b905083610ea6565b9050905b610b8581856108b9565b821015610ba257610b99610b859284610ea6565b90509150610b7b565b50505050565b6305787a5560e41b5f5260045ffd5b908151811015610bc8570160200190565b634e487b7160e01b5f52603260045260245ffd5b60ff60f6199116019060ff821161087c57565b60ff60bf199116019060ff821161087c57565b60ff607f199116019060ff821161087c57565b60ff60b6199116019060ff821161087c57565b805115610d0757610c53610c4d610c3f5f84610bb7565b516001600160f81b03191690565b60f81c90565b9060ff821660bf8111610c69575050505f905f90565b60f710610c8d5750610c7d610c8391610bef565b60ff1690565b906107095f610881565b9190610c7d610c9b91610bdc565b610cad81610ca85f610881565b6108b9565b835110610cff575f925f905b828210610ccf57505061070990610ca85f610881565b909360019060081b610cf6610c7d610c4d610c3f610cf08a610ca85f610881565b87610bb7565b17940190610cb9565b505f91508190565b505f905f90565b9190918051831015610cff57610d2a610c4d610c3f8584610bb7565b9060ff821660bf8111610d425750505090505f905f90565b60f710610d5f5750610d59610c7d61070992610bef565b92610881565b9290610c7d610d6d91610bdc565b90610d7b82610ca883610881565b845110610dc7575f935f905b838210610d9d57505090610ca861070992610881565b909460019060081b610dbe610c7d610c4d610c3f610cf08b610ca88a610881565b17950190610d87565b505090505f905f90565b8051821015610ba857610dea610c4d610c3f8484610bb7565b60ff81169290607f8411610dfe5750505090565b90919392608081145f14610e1457505f93505050565b60818110159081610e9a575b5015610ba857610c7d610e3291610c02565b90610e4082610ca883610881565b845110610ba85792905f935f925b828410610e5b5750505050565b90919294610e7660019167ffffffffffffff009060081b1690565b610e8f610c7d610c4d610c3f610cf08b610ca88a610881565b179501929190610e4e565b6088915011155f610e20565b9190918051831015610ba857610ec2610c4d610c3f8584610bb7565b9060ff8216607f8111610ee15750505090610edc90610881565b600191565b60b78111610f0c575050610efa610c7d61070992610c02565b610ca8610f068261088f565b94610881565b60bf8111610f78575090610c7d610f2291610c15565b5f915f905b828210610f4e57505090610ca882610ca8610f4884610ca86107099761088f565b96610881565b909260019060081b610f6f610c7d610c4d610c3f610cf089610ca88d610881565b17930190610f27565b60f710610f8f5750610efa610c7d61070992610bef565b90610c7d610f9c91610bdc565b5f915f905b828210610fc257505090610ca882610ca8610f4884610ca86107099761088f565b909260019060081b610fe3610c7d610c4d610c3f610cf089610ca88d610881565b17930190610fa1565b602003906020821161087c57565b5f1981019190821161087c57565b600381901b91906001600160fd1b0381160361087c57565b908151811015610ba85761103a610c4d610c3f8385610bb7565b60ff81169060a082036110615750506110528161089d565b825110610ba857016021015190565b909290607f84116110725750505090565b909192608081101590816110e4575b5015610ba857610c7d61109391610c02565b91826110a0575050505f90565b60208311610ba8576110b583610ca883610881565b825110610ba8576110d96110d460216001936110df9501015194610fec565b611008565b1b610ffa565b191690565b60b7915011155f611081565b908151811015610ba85760ff61110c610c4d610c3f8486610bb7565b1660948103611131575061111f816108ab565b825110610ba857016021015160601c90565b608014159150610ba89050575f9056fea264697066735822122057b3592454e545ec01075f02fbae633b4e6428716576ab0cafcfaa18082bb5d064736f6c634300081e0033", + "code": "0x60806040526004361015610011575f80fd5b5f3560e01c80631d04645f146101245780632245d0831461011f5780632e224dee1461011a5780633d7a27611461011557806346903867146101105780634732f8bb1461010b57806352d922a51461010657806358c3659914610101578063615cf854146100fc5780636aba6931146100f757806380a4cbc8146100f257806381e3da6b146100ed5780639a7361eb146100e8578063c334cd20146100e3578063f3b52855146100de578063f495be0b146100d95763fe770099146100d4575f80fd5b61052e565b610505565b6104dc565b6104bf565b6104a2565b610345565b610329565b6102b1565b61023a565b610214565b6101f7565b6101d1565b6101b1565b610194565b610177565b61014e565b3461014a575f36600319011261014a5760206001600160401b0360075416604051908152f35b5f80fd5b3461014a575f36600319011261014a5760206001600160401b0360015460401c16604051908152f35b3461014a575f36600319011261014a576020600454604051908152f35b3461014a575f36600319011261014a576020600954604051908152f35b3461014a575f36600319011261014a57602060075460c01c604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360085416604051908152f35b3461014a575f36600319011261014a576020600254604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360015416604051908152f35b3461014a575f36600319011261014a576003546040516001600160a01b039091168152602090f35b600435906001600160a01b038216820361014a57565b60206040818301928281528451809452019201905f5b81811061029b5750505090565b825184526020938401939092019160010161028e565b3461014a57604036600319011261014a576102ca610262565b6024356001600160401b03811161014a573660238201121561014a5780600401356001600160401b03811161014a573660248260051b8401011161014a57610325926024610319930190610655565b60405191829182610278565b0390f35b3461014a575f36600319011261014a5760205f54604051908152f35b3461014a57604036600319011261014a5761035e610262565b3360016007609a1b01141580610491575b80610480575b61041557600754604051631e7d027560e31b81526001600160a01b03909216600483015260248035908301526001600160401b0316604482015260208160648160046007609a1b015afa801561041057610325915f916103e1575b506040519081529081906020820190565b610403915060203d602011610409575b6103fb8183610742565b8101906107f6565b5f6103d0565b503d6103f1565b6107eb565b60405162461bcd60e51b815260206004820152603b60248201527f54656d706f53746174653a206f6e6c79207a6f6e652073797374656d20636f6e60448201527f7472616374732063616e20726561642054656d706f20737461746500000000006064820152608490fd5b503360036007609a1b011415610375565b503360026007609a1b01141561036f565b3461014a575f36600319011261014a576020600554604051908152f35b3461014a575f36600319011261014a576020600654604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360075460401c16604051908152f35b3461014a575f36600319011261014a5760206001600160401b0360075460801c16604051908152f35b3461014a57602036600319011261014a576004356001600160401b03811161014a573660238201121561014a578060040135906001600160401b03821161014a57366024838301011161014a576007609a1b193301610646576105b26105ad5f54926105a26007546001600160401b031690565b946024369201610805565b6108c6565b60025403610637576001600160401b036105ec6105e06105da6007546001600160401b031690565b9361085e565b6001600160401b031690565b9116908103610628575f546004546040519081527fdd85219569c3c880f014955916f426d1ca039714b59ce33e24f151f155ac26b990602090a3005b631391e11b60e21b5f5260045ffd5b63591c836760e01b5f5260045ffd5b6303300c7360e31b5f5260045ffd5b91903360016007609a1b0114158061071d575b8061070c575b61041557600754604051632593f8c960e01b81526001600160a01b03909416600485015260606024850152606484018390526001600160401b03166001600160fb1b03831161014a578380926084925f9560051b8092858501376044830152810103018160046007609a1b015afa908115610410575f916106ed575090565b61070991503d805f833e6107018183610742565b810190610768565b90565b503360036007609a1b01141561066e565b503360026007609a1b011415610668565b634e487b7160e01b5f52604160045260245ffd5b90601f801991011681019081106001600160401b0382111761076357604052565b61072e565b60208183031261014a578051906001600160401b03821161014a57019080601f8301121561014a578151916001600160401b038311610763578260051b90604051936107b76020840186610742565b845260208085019282010192831161014a57602001905b8282106107db5750505090565b81518152602091820191016107ce565b6040513d5f823e3d90fd5b9081602091031261014a575190565b9291926001600160401b038211610763576040519161082e601f8201601f191660200184610742565b82948184528183011161014a578281602093845f960137010152565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b036001911601906001600160401b03821161087c57565b61084a565b906001820180921161087c57565b600101908160011161087c57565b906021820180921161087c57565b906015820180921161087c57565b9190820180921161087c57565b805160208201205f556108d881610c28565b80915015610ba85761098b61095a61091c836109166108fa6109939688610dd1565b6001600160401b03166001600160401b03196001541617600155565b85610ea6565b905061095461092b8287610dd1565b67ffffffffffffffff60401b6001549160401b169067ffffffffffffffff60401b191617600155565b84610ea6565b90506109856109698286610dd1565b6001600160401b03166001600160401b03196008541617600855565b83610ea6565b905082610d0e565b91908215610ba857610b77610b6f610b5b610b53610b1f610add610aa5610a74610a6c610a648b610a5e610a598f610a3c610a286109f16109e9846109e36109de610a50978b611020565b600255565b88610ea6565b905087610ea6565b9050610a22610a0082896110f0565b60018060a01b03166bffffffffffffffffffffffff60a01b6003541617600355565b86610ea6565b9050610916610a378288611020565b600455565b9050610954610a4b8287611020565b600555565b93849150611020565b600655565b8c610ea6565b90508b610ea6565b90508a610ea6565b9050610a9f610a83828c610dd1565b6001600160401b03166001600160401b03196007541617600755565b89610ea6565b90506109e3610ab4828b610dd1565b67ffffffffffffffff60401b6007549160401b169067ffffffffffffffff60401b191617600755565b9050610b19610aec828a610dd1565b6007805467ffffffffffffffff60801b191660809290921b67ffffffffffffffff60801b16919091179055565b87610ea6565b9050610a22610b2e8289610dd1565b600780546001600160c01b031660c09290921b6001600160c01b031916919091179055565b905085610ea6565b9050610954610b6a8287611020565b600955565b905083610ea6565b9050905b610b8581856108b9565b821015610ba257610b99610b859284610ea6565b90509150610b7b565b50505050565b6305787a5560e41b5f5260045ffd5b908151811015610bc8570160200190565b634e487b7160e01b5f52603260045260245ffd5b60ff60f6199116019060ff821161087c57565b60ff60bf199116019060ff821161087c57565b60ff607f199116019060ff821161087c57565b60ff60b6199116019060ff821161087c57565b805115610d0757610c53610c4d610c3f5f84610bb7565b516001600160f81b03191690565b60f81c90565b9060ff821660bf8111610c69575050505f905f90565b60f710610c8d5750610c7d610c8391610bef565b60ff1690565b906107095f610881565b9190610c7d610c9b91610bdc565b610cad81610ca85f610881565b6108b9565b835110610cff575f925f905b828210610ccf57505061070990610ca85f610881565b909360019060081b610cf6610c7d610c4d610c3f610cf08a610ca85f610881565b87610bb7565b17940190610cb9565b505f91508190565b505f905f90565b9190918051831015610cff57610d2a610c4d610c3f8584610bb7565b9060ff821660bf8111610d425750505090505f905f90565b60f710610d5f5750610d59610c7d61070992610bef565b92610881565b9290610c7d610d6d91610bdc565b90610d7b82610ca883610881565b845110610dc7575f935f905b838210610d9d57505090610ca861070992610881565b909460019060081b610dbe610c7d610c4d610c3f610cf08b610ca88a610881565b17950190610d87565b505090505f905f90565b8051821015610ba857610dea610c4d610c3f8484610bb7565b60ff81169290607f8411610dfe5750505090565b90919392608081145f14610e1457505f93505050565b60818110159081610e9a575b5015610ba857610c7d610e3291610c02565b90610e4082610ca883610881565b845110610ba85792905f935f925b828410610e5b5750505050565b90919294610e7660019167ffffffffffffff009060081b1690565b610e8f610c7d610c4d610c3f610cf08b610ca88a610881565b179501929190610e4e565b6088915011155f610e20565b9190918051831015610ba857610ec2610c4d610c3f8584610bb7565b9060ff8216607f8111610ee15750505090610edc90610881565b600191565b60b78111610f0c575050610efa610c7d61070992610c02565b610ca8610f068261088f565b94610881565b60bf8111610f78575090610c7d610f2291610c15565b5f915f905b828210610f4e57505090610ca882610ca8610f4884610ca86107099761088f565b96610881565b909260019060081b610f6f610c7d610c4d610c3f610cf089610ca88d610881565b17930190610f27565b60f710610f8f5750610efa610c7d61070992610bef565b90610c7d610f9c91610bdc565b5f915f905b828210610fc257505090610ca882610ca8610f4884610ca86107099761088f565b909260019060081b610fe3610c7d610c4d610c3f610cf089610ca88d610881565b17930190610fa1565b602003906020821161087c57565b5f1981019190821161087c57565b600381901b91906001600160fd1b0381160361087c57565b908151811015610ba85761103a610c4d610c3f8385610bb7565b60ff81169060a082036110615750506110528161089d565b825110610ba857016021015190565b909290607f84116110725750505090565b909192608081101590816110e4575b5015610ba857610c7d61109391610c02565b91826110a0575050505f90565b60208311610ba8576110b583610ca883610881565b825110610ba8576110d96110d460216001936110df9501015194610fec565b611008565b1b610ffa565b191690565b60b7915011155f611081565b908151811015610ba85760ff61110c610c4d610c3f8486610bb7565b1660948103611131575061111f816108ab565b825110610ba857016021015160601c90565b608014159150610ba89050575f9056fea2646970667358221220de5b6706c2b17c429955607698a559d3537d3785b13cf012a01a22419972e1b864736f6c634300081e0033", "storage": { "0x0000000000000000000000000000000000000000000000000000000000000000": "0xb049644b1d5a0ec9d785dd48f95099e0f566112084acb1ba0814112209b432a1", "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -58,17 +58,17 @@ "0x1c00000000000000000000000000000000000001": { "nonce": "0x1", "balance": "0x0", - "code": "0x60806040526004361015610011575f80fd5b5f3560e01c80631fbb25ad146100745780632d4884821461006f57806379502c551461006a57806382648c3b1461006557806397cac0fb146100605763a21de6d91461005b575f80fd5b61026c565b6101ac565b610130565b6100ec565b6100c6565b346100b8575f3660031901126100b8577f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b03166080908152602090f35b5f80fd5b5f9103126100b857565b346100b8575f3660031901126100b85760206001600160401b0360015416604051908152f35b346100b8575f3660031901126100b8576040517f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03168152602090f35b346100b8575f3660031901126100b85760205f54604051908152f35b9181601f840112156100b8578235916001600160401b0383116100b8576020808501948460051b0101116100b857565b9181601f840112156100b8578235916001600160401b0383116100b8576020808501948460071b0101116100b857565b346100b85760803660031901126100b8576004356001600160401b0381116100b857366023820112156100b8578060040135906001600160401b0382116100b85736602483830101116100b8576024356001600160401b0381116100b85761021890369060040161014c565b6044929192356001600160401b0381116100b85761023a90369060040161017c565b91606435946001600160401b0386116100b85761026a96610261602497369060040161014c565b979096016109d1565b005b346100b8575f3660031901126100b8576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b634e487b7160e01b5f52604160045260245ffd5b60a081019081106001600160401b038211176102df57604052565b6102b0565b90601f801991011681019081106001600160401b038211176102df57604052565b6001600160a01b038116036100b857565b908160209103126100b8575161032b81610305565b90565b6040513d5f823e3d90fd5b908060209392818452848401375f828201840152601f01601f1916010190565b91602061032b938181520191610339565b634e487b7160e01b5f52603260045260245ffd5b91908110156103a05760051b81013590607e19813603018212156100b8570190565b61036a565b3561032b81610305565b903590601e19813603018212156100b857018035906001600160401b0382116100b8576020019181360383136100b857565b95939161040d9061041b9461032b99979360018060a01b03168952608060208a01526080890191610339565b918683036040880152610339565b926060818503910152610339565b9492909361044761032b979561045594606089526060890191610339565b918683036020880152610339565b926040818503910152610339565b91908110156103a05760051b81013590603e19813603018212156100b8570190565b6002111561048f57565b634e487b7160e01b5f52602160045260245ffd5b3560028110156100b85790565b35906001600160801b03821682036100b857565b60ff8116036100b857565b6001600160401b0381116102df57601f01601f191660200190565b35906001600160a01b0319821682036100b857565b35906001600160801b0319821682036100b857565b919060a0838203126100b8576040519061052d826102c4565b8193803583526020810135610541816104c4565b602084015260408101356001600160401b0381116100b857810182601f820112156100b857803591610572836104cf565b9361058060405195866102e4565b838552602084840101116100b8576080935f6020856105c19682899701838601378301015260408601526105b6606082016104ea565b6060860152016104ff565b910152565b6020818303126100b8578035906001600160401b0382116100b8570160a0818303126100b857604051916105f9836102c4565b813561060481610305565b8352602082013561061481610305565b6020840152610625604083016104b0565b60408401526060820135606084015260808201356001600160401b0381116100b8576106519201610514565b608082015290565b634e487b7160e01b5f52601160045260245ffd5b5f19811461067b5760010190565b610659565b91908110156103a05760071b0190565b3561032b816104c4565b519081151582036100b857565b908160209103126100b85761032b9061069a565b604051906106ca6040836102e4565b600d82526c65636965732d6165732d6b657960981b6020830152565b91906040838203126100b85782516001600160401b0381116100b857830181601f820112156100b85780519161071b836104cf565b9061072960405192836102e4565b838252602084840101116100b8575f60208461032b95828096018386015e83010152930161069a565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b926107ac9060809360209397969786526bffffffffffffffffffffffff60a01b168386015260a0604086015260a0850190610752565b83810360608501525f815201936001600160801b031916910152565b90600282101561048f5752565b92919060806040916107e88660016107c8565b6060602087015260018060a01b03815116606087015260018060a01b03602082015116828701526001600160801b03838201511660a0870152606081015160c0870152015160a060e0860152805161010086015260ff6020820151166101208601526108648282015160a06101408801526101a0870190610752565b60608201516001600160a01b0319166101608701526080909101516001600160801b031916610180860152930152565b6001600160a01b0390911681526001600160801b03909116602082015260400190565b908160a09103126100b8576080604051916108d1836102c4565b80356108dc81610305565b835260208101356108ec81610305565b602084015260408101356108ff81610305565b6040840152610910606082016104b0565b60608401520135608082015290565b60c09093929193608060e0820195610937835f6107c8565b80516001600160a01b039081166020858101919091528201518116604080860191909152820151166060808501919091528101516001600160801b031682840152015160a08201520152565b908160209103126100b8575190565b906001600160401b03809116911601906001600160401b03821161067b57565b908160209103126100b857516001600160401b03811681036100b85790565b9591949392969033151580611482575b611473577f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b031696873b156100b85760405163fe77009960e01b8152915f9183918291610a39919060048401610359565b0381838b5af18015610c015761145f575b505f9492945b818110611344575050505f54925f915f915b878310610c675750505003610c58576040516381e3da6b60e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166004808301919091526024820152602081604481865afa8015610c0157610c3b575b50805f55610b11610af56001600160401b038516610af06001546001600160401b031690565b610992565b6001600160401b03166001600160401b03196001541617600155565b604051631014997960e31b815291602083600481845afa928315610c01575f93610c06575b50602060049160405192838092631d04645f60e01b82525afa8015610c01577fd2d2bf1e295f62cd08f0f0ab45818efeaba78b58310526f7b7e9686b8aeded1a926001600160401b03925f92610bcc575b50610bc790610b9e6001546001600160401b031690565b6040805198895260208901929092526001600160401b0316908701529116939081906060820190565b0390a3565b610bc7919250610bf39060203d602011610bfa575b610beb81836102e4565b8101906109b2565b9190610b87565b503d610be1565b61032e565b6004919350610c2c602091823d8411610c34575b610c2481836102e4565b810190610983565b939150610b36565b503d610c1a565b610c539060203d602011610c3457610c2481836102e4565b610aca565b6361aba18160e11b5f5260045ffd5b909194610c75868985610463565b610c7e816104a3565b610c8781610485565b610e2857610c9c816020610ca49301906103af565b8101906108b7565b90604051610cc981610cbb6020820194868661091f565b03601f1981018352826102e4565b5190208151909690610cf190610ce5906001600160a01b031681565b6001600160a01b031690565b6040830180519091906001600160a01b0316906060850191610d1a83516001600160801b031690565b823b156100b857610d44925f92836040518096819582946340c10f1960e01b845260048401610894565b03925af18015610c01576001958b927fd5277bc9597c7da3fab9cdbba4de6005f48b9eb7389cf2389c4ea9eea3172c2192610e0e575b506020810151610d9b906001600160a01b031695516001600160a01b031690565b8151610e0290608090610dbf906001600160a01b031697516001600160801b031690565b930151604080516001600160a01b0390981688526001600160801b0390941660208801529286019290925260a088901b8890039081169516939081906060820190565b0390a45b019190610a62565b80610e1c5f610e22936102e4565b806100bc565b5f610d7a565b610e3c816020610e449399949901906103af565b8101906105c6565b908585101561133557610ef696610e65610e5d8761066d565b968886610680565b6060840160406020610e778351611542565b929094608089019d8e51610e9085825192015160ff1690565b95833598610e9f878601610690565b8651635f8a996960e01b8152600481019490945260ff9889166024850152604484018b905288166064840152608483015290951660a48601529101803560c48501526020013560e484015282908190610104820190565b0381731c000000000000000000000000000000000001005afa908115610c01575f91611307575b50156112f857518951516040516bffffffffffffffffffffffff197f000000000000000000000000000000000000000000000000000000000000000060601b166020820152603481019290925260548083019190915281525f91610f959190610f876074836102e4565b610f8f6106bb565b906116b3565b98518099610fed610fd260806040610fbf60608701516bffffffffffffffffffffffff60a01b1690565b9501519d01516001600160801b03191690565b60405163f4a7eb1360e01b81529c8d94859460048601610776565b0381731c000000000000000000000000000000000001015afa978815610c01575f905f996112d1575b505f808a806112c6575b156112ba5750506110309061171f565b90915b60405161104981610cbb602082019489866107d5565b5190209861115b575050815161106990610ce5906001600160a01b031681565b602083018051909391906001600160a01b031691604081019261109384516001600160801b031690565b833b156100b8576110bd935f92836040518097819582946340c10f1960e01b845260048401610894565b03925af1908115610c015761112761111961110b6001988e967f95705d99ac13cf82894fd274cd871942e6f301c98c186271337e8fedbbb9d7ea96611147575b50516001600160a01b031690565b92516001600160a01b031690565b94516001600160801b031690565b9061113f604051928392898060a01b03169683610894565b0390a3610e06565b80610e1c5f611155936102e4565b5f6110fd565b835161117190610ce5906001600160a01b031681565b90604085019261118884516001600160801b031690565b833b156100b8575f6111b48d9582936040519485809481936340c10f1960e01b83528960048401610894565b03925af190816112a6575b506111ff57505083516111dd9150610ce5906001600160a01b031681565b6020840180519094906001600160a01b031683516001600160801b0316611093565b859392917ffc236d1b4402e76c2b0a882db36ad3a6fb0f5b6b7edc8ae317d993f10434c4369161129e61125f611251611243602060019c015160018060a01b031690565b98516001600160a01b031690565b96516001600160801b031690565b604080516001600160a01b0390981688526001600160801b03909116602088015286019290925260a088901b8890039081169516939081906060820190565b0390a4610e06565b80610e1c5f6112b4936102e4565b5f6111bf565b91509198505f98611033565b506040835114611020565b90506112f09198503d805f833e6112e881836102e4565b8101906106e6565b97905f611016565b63fb1f4a4960e01b5f5260045ffd5b611328915060203d811161132e575b61132081836102e4565b8101906106a7565b5f610f1d565b503d611316565b6351de8c1f60e01b5f5260045ffd5b61135281838598969861037e565b9061135c826103a5565b91602081019061136c82826103af565b9092604083019361137d85856103af565b919097606086019861138f8a886103af565b9061083f60921b3b156100b8575f956113bd93604051998a9788976374ae5b3760e11b8952600489016103e1565b03818361083f60921b5af18015610c01576001967f4ac4dcc08b0c26c3fb6b58c64c1392b7934b1ce6b0382a5986ea5c3de795e053946114209461143f9361144b575b50611428611417611410836103a5565b95836103af565b969098836103af565b9390926103af565b9290916040519687968c8060a01b03169987610429565b0390a201949294610a50565b80610e1c5f611459936102e4565b5f611400565b80610e1c5f61146d936102e4565b5f610a4a565b63bb62587160e01b5f5260045ffd5b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610c01575f916114e2575b506001600160a01b03163314156109e1565b611504915060203d60201161150a575b6114fc81836102e4565b810190610316565b5f6114d0565b503d6114f2565b908160011b918083046002149015171561067b57565b906001820180921161067b57565b9190820180921161067b57565b6115739061156d604051602081019061156481610cbb84906006602083019252565b51902091611511565b90611535565b906115fc61158083611527565b6040516381e3da6b60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000818116600484015260248301969096527f0000000000000000000000001c0000000000000000000000000000000000000016949092909190602090849081906044820190565b0381885afa928315610c01575f93611680575b5082156112f8576040516381e3da6b60e01b81526001600160a01b03929092166004830152602482015292602090849060449082905afa928315610c01575f9361165c575b509160ff1690565b60ff9193506116799060203d602011610c3457610c2481836102e4565b9290611654565b61169a91935060203d602011610c3457610c2481836102e4565b915f61160f565b805191908290602001825e015f815290565b9161170760016116e161032b956116f295604051916020830152602082526116dc6040836102e4565b611768565b9260405194859160208301906116a1565b8260f81b815203601e198101855201836102e4565b604051906020820152602081526116dc6040826102e4565b9081516040810361173b57506034602083015160601c92015190565b633fbbeba160e21b5f52600452604060245260445ffd5b61032b93926040928252602082015201906116a1565b5f908051604081115f1461187457505f61178a602092604051918280926116a1565b039060025afa15610c015760205f611805610cbb6117f98351965b6040519283917f363636363636363636363636363636363636363636363636363636363636363689187f36363636363636363636363636363636363636363636363636363636363636368b18898501611752565b604051918280926116a1565b039060025afa15610c01576118647f5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c6117f95f93610cbb6020968651908560405196879518911889850191606093918352602083015260408201520190565b039060025afa15610c01575f5190565b60208083015194908211935091600184146118e357505f925b602082106118cd575b60408210166118b3575b505f611805610cbb6117f96020946117a5565b600160409190910360031b1b5f190119909116905f6118a0565b935f1960018360200360031b1b01191693611896565b604001519261188d56fea26469706673582212208e93ef9bfe51376039a34783438753d575cafb9c32630db748d87afe43a51c4a64736f6c634300081e0033" + "code": "0x60806040526004361015610011575f80fd5b5f3560e01c80631fbb25ad146100845780632d4884821461007f57806379502c551461007a57806382648c3b14610075578063a21de6d914610070578063ce11e6ab1461006b5763d01e8d3114610066575f80fd5b610244565b6101a0565b61015c565b610140565b6100fc565b6100d6565b346100c8575f3660031901126100c8577f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b03166080908152602090f35b5f80fd5b5f9103126100c857565b346100c8575f3660031901126100c85760206001600160401b0360015416604051908152f35b346100c8575f3660031901126100c8576040517f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03168152602090f35b346100c8575f3660031901126100c85760205f54604051908152f35b346100c8575f3660031901126100c8576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346100c8575f3660031901126100c8576040517f0000000000000000000000001c000000000000000000000000000000000000026001600160a01b03168152602090f35b9181601f840112156100c8578235916001600160401b0383116100c8576020808501948460051b0101116100c857565b9181601f840112156100c8578235916001600160401b0383116100c85760208085019460c085020101116100c857565b346100c85760803660031901126100c8576004356001600160401b0381116100c857366023820112156100c8578060040135906001600160401b0382116100c85736602483830101116100c8576024356001600160401b0381116100c8576102b09036906004016101e4565b6044929192356001600160401b0381116100c8576102d2903690600401610214565b91606435946001600160401b0386116100c857610302966102f960249736906004016101e4565b97909601610acb565b005b634e487b7160e01b5f52604160045260245ffd5b60a081019081106001600160401b0382111761033357604052565b610304565b60c081019081106001600160401b0382111761033357604052565b90601f801991011681019081106001600160401b0382111761033357604052565b6001600160a01b038116036100c857565b908160209103126100c8575161039a81610374565b90565b6040513d5f823e3d90fd5b908060209392818452848401375f828201840152601f01601f1916010190565b91602061039a9381815201916103a8565b634e487b7160e01b5f52603260045260245ffd5b919081101561040f5760051b81013590607e19813603018212156100c8570190565b6103d9565b3561039a81610374565b903590601e19813603018212156100c857018035906001600160401b0382116100c8576020019181360383136100c857565b95939161047c9061048a9461039a99979360018060a01b03168952608060208a015260808901916103a8565b9186830360408801526103a8565b9260608185039101526103a8565b949290936104b661039a97956104c4946060895260608901916103a8565b9186830360208801526103a8565b9260408185039101526103a8565b919081101561040f5760051b81013590603e19813603018212156100c8570190565b600211156104fe57565b634e487b7160e01b5f52602160045260245ffd5b3560028110156100c85790565b359061052a82610374565b565b35906001600160801b03821682036100c857565b60ff8116036100c857565b6001600160401b03811161033357601f01601f191660200190565b35906001600160a01b0319821682036100c857565b35906001600160801b0319821682036100c857565b919060a0838203126100c857604051906105a982610318565b81938035835260208101356105bd81610540565b602084015260408101356001600160401b0381116100c857810182601f820112156100c8578035916105ee8361054b565b936105fc6040519586610353565b838552602084840101116100c8576080935f60208561063d96828997018386013783010152604086015261063260608201610566565b60608601520161057b565b910152565b6020818303126100c8578035906001600160401b0382116100c8570160c0818303126100c8576040519161067583610338565b813561068081610374565b835261068e6020830161051f565b602084015261069f6040830161052c565b6040840152606082013560608401526080820135916001600160401b0383116100c8576106d360a0926106de948301610590565b60808501520161051f565b60a082015290565b634e487b7160e01b5f52601160045260245ffd5b5f1981146107085760010190565b6106e6565b919081101561040f5760c0020190565b3561039a81610540565b519081151582036100c857565b908160209103126100c85761039a90610727565b60405190610757604083610353565b600d82526c65636965732d6165732d6b657960981b6020830152565b91906040838203126100c85782516001600160401b0381116100c857830181601f820112156100c8578051916107a88361054b565b906107b66040519283610353565b838252602084840101116100c8575f60208461039a95828096018386015e830101529301610727565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b926108399060809360209397969786526bffffffffffffffffffffffff60a01b168386015260a0604086015260a08501906107df565b83810360608501525f815201936001600160801b031916910152565b9060028210156104fe5752565b929190604090610873856001610855565b6060602086015260018060a01b03815116606086015260018060a01b0360208201511660808601526001600160801b03828201511660a0860152606081015160c086015261093c60a060808301519260c060e0890152835161012089015260ff6020850151166101408901526108f885850151836101608b01526101c08a01906107df565b60608501516bffffffffffffffffffffffff841b166101808a01526080909401516001600160801b0319166101a089015201516001600160a01b0316610100870152565b930152565b6001600160a01b0390911681526001600160801b03909116602082015260400190565b6001600160a01b0391821681526001600160801b039092166020830152909116604082015260600190565b908160c09103126100c85760a0604051916109a983610338565b80356109b481610374565b835260208101356109c481610374565b602084015260408101356109d781610374565b60408401526109e86060820161052c565b60608401526080810135608084015201356106de81610374565b610100810193929160e09190610a18825f610855565b60018060a01b03815116602083015260018060a01b03602082015116604083015260018060a01b0360408201511660608301526001600160801b036060820151166080830152608081015160a083015260a0600180821b039101511660c08201520152565b908160209103126100c8575190565b906001600160401b03809116911601906001600160401b03821161070857565b908160209103126100c857516001600160401b03811681036100c85790565b9591949392969033151580611afa575b611aeb577f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b031696873b156100c85760405163fe77009960e01b8152915f9183918291610b339190600484016103c8565b0381838b5af18015610cfb57611ad7575b505f9492945b8181106119bc575050505f54925f915f915b878310610d615750505003610d52576040516381e3da6b60e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166004808301919091526024820152602081604481865afa8015610cfb57610d35575b50805f55610c0b610bef6001600160401b038516610bea6001546001600160401b031690565b610a8c565b6001600160401b03166001600160401b03196001541617600155565b604051631014997960e31b815291602083600481845afa928315610cfb575f93610d00575b50602060049160405192838092631d04645f60e01b82525afa8015610cfb577fd2d2bf1e295f62cd08f0f0ab45818efeaba78b58310526f7b7e9686b8aeded1a926001600160401b03925f92610cc6575b50610cc190610c986001546001600160401b031690565b6040805198895260208901929092526001600160401b0316908701529116939081906060820190565b0390a3565b610cc1919250610ced9060203d602011610cf4575b610ce58183610353565b810190610aac565b9190610c81565b503d610cdb565b61039d565b6004919350610d26602091823d8411610d2e575b610d1e8183610353565b810190610a7d565b939150610c30565b503d610d14565b610d4d9060203d602011610d2e57610d1e8183610353565b610bc4565b6361aba18160e11b5f5260045ffd5b909194610d6f8689856104d2565b610d7881610512565b610d81816104f4565b61117957610d96816020610d9e93019061041e565b81019061098f565b90604051610dc381610db560208201948686610a02565b03601f198101835282610353565b5190209560a0820191610deb610ddf845160018060a01b031690565b6001600160a01b031690565b156110ab578051610e0690610ddf906001600160a01b031681565b604082018051909491906001600160a01b03166060840191610e2f83516001600160801b031690565b91813b156100c8578c92610e5c925f92836040518096819582946340c10f1960e01b845260048401610941565b03925af19081611097575b50610fdb575082516001600160a01b037f0000000000000000000000001c00000000000000000000000000000000000002811692911681516001600160801b031684519093906001600160a01b031690803b156100c857610ee2945f8094604051978895869485936338b8fb9760e21b855260048501610964565b03925af1958615610cfb57610fb58c947f3c1af70310b8c9d43b0a7207217f398e4a3114f1728987c40addb451399ac87c94600199610fc1575b506020870151610f7390610f6590610f5790610f49906001600160a01b031696516001600160a01b031690565b99516001600160a01b031690565b95516001600160801b031690565b91516001600160a01b031690565b906040519485948b8060a01b031698856001600160a01b03918216815291811660208301526001600160801b0390921660408201529116606082015260800190565b0390a35b019190610b5c565b80610fcf5f610fd593610353565b806100cc565b5f610f1c565b60208401516001969492935090917fd5277bc9597c7da3fab9cdbba4de6005f48b9eb7389cf2389c4ea9eea3172c2191611027906001600160a01b03165b95516001600160a01b031690565b815161108f9060809061104c906001600160a01b03165b97516001600160801b031690565b930151604080516001600160a01b0390981688526001600160801b0390941660208801529286019290925260a088901b8890039081169516939081906060820190565b0390a4610fb9565b80610fcf5f6110a593610353565b5f610e67565b80519092506110c490610ddf906001600160a01b031681565b6040830180519091906001600160a01b03169060608501916110ed83516001600160801b031690565b823b156100c857611117925f92836040518096819582946340c10f1960e01b845260048401610941565b03925af18015610cfb576001958b927fd5277bc9597c7da3fab9cdbba4de6005f48b9eb7389cf2389c4ea9eea3172c2192611165575b506020810151611027906001600160a01b0316611019565b80610fcf5f61117393610353565b5f61114d565b61118d81602061119593999499019061041e565b810190610642565b90858510156119ad576111b26111aa866106fa565b95878561070d565b606083016111c08151611bba565b916080860192602060808661124687516111df85825192015160ff1690565b958335986111ee87860161071d565b604051635f8a996960e01b8152600481019490945260ff9889166024850152604484018b905288166064840152608483015290951660a48601529101803560c48501526020013560e484015282908190610104820190565b0381731c000000000000000000000000000000000001005afa908115610cfb575f9161197f575b501561197057518251516040516bffffffffffffffffffffffff197f000000000000000000000000000000000000000000000000000000000000000060601b166020820152603481019290925260548083019190915281525f916112e591906112d7607483610353565b6112df610748565b90611d2b565b915160608101519092906001600160a01b03191690611332611317608060408701519601516001600160801b03191690565b60405163f4a7eb1360e01b8152958694859460048601610803565b0381731c000000000000000000000000000000000001015afa8015610cfb575f915f9161194c575b5080611941575b156119395761136f90611d97565b9061137f610ddf60408501610414565b6001600160a01b0390911614908161192b575b50975b6040516113ab81610db560208201948886610862565b5190209761162b575060a0820180516113cc906001600160a01b0316610ddf565b156115c05782516113e790610ddf906001600160a01b031681565b6020840180519094919291906001600160a01b0316604082019361141285516001600160801b031690565b91813b156100c8578c9261143f925f92836040518096819582946340c10f1960e01b845260048401610941565b03925af190816115ac575b5061156c575080516001600160a01b037f0000000000000000000000001c0000000000000000000000000000000000000281169116906114a261149486516001600160801b031690565b94516001600160a01b031690565b90803b156100c8576114ce945f8094604051978895869485936338b8fb9760e21b855260048501610964565b03925af1908115610cfb5761153861152a61151c6001988e967f95705d99ac13cf82894fd274cd871942e6f301c98c186271337e8fedbbb9d7ea96611558575b50516001600160a01b031690565b92516001600160a01b031690565b94516001600160801b031690565b90611550604051928392898060a01b03169683610941565b0390a3610fb9565b80610fcf5f61156693610353565b5f61150e565b945160019592507f95705d99ac13cf82894fd274cd871942e6f301c98c186271337e8fedbbb9d7ea91906115389061152a906001600160a01b031661151c565b80610fcf5f6115ba93610353565b5f61144a565b5081516115d790610ddf906001600160a01b031681565b602083018051909391906001600160a01b031691604081019261160184516001600160801b031690565b833b156100c8576114ce935f92836040518097819582946340c10f1960e01b845260048401610941565b60a083018051919391611646906001600160a01b0316610ddf565b1561185457815161166190610ddf906001600160a01b031681565b604085019461166f86610414565b90604085019261168684516001600160801b031690565b92813b156100c8578d936116b3925f92836040518096819582946340c10f1960e01b845260048401610941565b03925af19081611840575b506117ad57505082516001600160a01b037f0000000000000000000000001c00000000000000000000000000000000000002811692911681516001600160801b031684519093906001600160a01b031690803b156100c85761173a945f8094604051978895869485936338b8fb9760e21b855260048501610964565b03925af1958615610cfb576115508c947f3c1af70310b8c9d43b0a7207217f398e4a3114f1728987c40addb451399ac87c94600199611799575b506020870151610f7390610f6590610f5790610f49906001600160a01b031696610414565b80610fcf5f6117a793610353565b5f611774565b7ffc236d1b4402e76c2b0a882db36ad3a6fb0f5b6b7edc8ae317d993f10434c436919293508461108f60606117fd61103e6114946117f7602060019e9c015160018060a01b031690565b9a610414565b604080516001600160a01b0390991689526001600160801b0390911660208901529301359286019290925260a088901b8890039081169516939081906060820190565b80610fcf5f61184e93610353565b5f6116be565b50805190929061186e90610ddf906001600160a01b031681565b90604081019161187d83610414565b91604086019261189484516001600160801b031690565b833b156100c8576118be935f92836040518097819582946340c10f1960e01b845260048401610941565b03925af1908115610cfb576001968c937ffc236d1b4402e76c2b0a882db36ad3a6fb0f5b6b7edc8ae317d993f10434c43693611917575b5061108f60606117fd61103e6114946117f7602087015160018060a01b031690565b80610fcf5f61192593610353565b5f6118f5565b90506060820135145f611392565b505f97611395565b506040815114611361565b905061196a91503d805f833e6119628183610353565b810190610773565b5f61135a565b63fb1f4a4960e01b5f5260045ffd5b6119a0915060203d81116119a6575b6119988183610353565b810190610734565b5f61126d565b503d61198e565b6351de8c1f60e01b5f5260045ffd5b6119ca8183859896986103ed565b906119d482610414565b9160208101906119e4828261041e565b909260408301936119f5858561041e565b9190976060860198611a078a8861041e565b9061083f60921b3b156100c8575f95611a3593604051998a9788976374ae5b3760e11b895260048901610450565b03818361083f60921b5af18015610cfb576001967f4ac4dcc08b0c26c3fb6b58c64c1392b7934b1ce6b0382a5986ea5c3de795e05394611a9894611ab793611ac3575b50611aa0611a8f611a8883610414565b958361041e565b9690988361041e565b93909261041e565b9290916040519687968c8060a01b03169987610498565b0390a201949294610b4a565b80610fcf5f611ad193610353565b5f611a78565b80610fcf5f611ae593610353565b5f610b44565b63bb62587160e01b5f5260045ffd5b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610cfb575f91611b5a575b506001600160a01b0316331415610adb565b611b7c915060203d602011611b82575b611b748183610353565b810190610385565b5f611b48565b503d611b6a565b908160011b918083046002149015171561070857565b906001820180921161070857565b9190820180921161070857565b611beb90611be56040516020810190611bdc81610db584906006602083019252565b51902091611b89565b90611bad565b90611c74611bf883611b9f565b6040516381e3da6b60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000818116600484015260248301969096527f0000000000000000000000001c0000000000000000000000000000000000000016949092909190602090849081906044820190565b0381885afa928315610cfb575f93611cf8575b508215611970576040516381e3da6b60e01b81526001600160a01b03929092166004830152602482015292602090849060449082905afa928315610cfb575f93611cd4575b509160ff1690565b60ff919350611cf19060203d602011610d2e57610d1e8183610353565b9290611ccc565b611d1291935060203d602011610d2e57610d1e8183610353565b915f611c87565b805191908290602001825e015f815290565b91611d7f6001611d5961039a95611d6a9560405191602083015260208252611d54604083610353565b611de0565b926040519485916020830190611d19565b8260f81b815203601e19810185520183610353565b60405190602082015260208152611d54604082610353565b90815160408103611db357506034602083015160601c92015190565b633fbbeba160e21b5f52600452604060245260445ffd5b61039a9392604092825260208201520190611d19565b5f908051604081115f14611eec57505f611e0260209260405191828092611d19565b039060025afa15610cfb5760205f611e7d610db5611e718351965b6040519283917f363636363636363636363636363636363636363636363636363636363636363689187f36363636363636363636363636363636363636363636363636363636363636368b18898501611dca565b60405191828092611d19565b039060025afa15610cfb57611edc7f5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c611e715f93610db56020968651908560405196879518911889850191606093918352602083015260408201520190565b039060025afa15610cfb575f5190565b6020808301519490821193509160018414611f5b57505f925b60208210611f45575b6040821016611f2b575b505f611e7d610db5611e71602094611e1d565b600160409190910360031b1b5f190119909116905f611f18565b935f1960018360200360031b1b01191693611f0e565b6040015192611f0556fea26469706673582212206791853311d53751fc5de422126d7d14022ca5ff0f1562bb69b859880af8e83264736f6c634300081e0033" }, "0x1c00000000000000000000000000000000000002": { "nonce": "0x1", "balance": "0x0", - "code": "0x60806040526004361015610011575f80fd5b5f3560e01c80632c37826e14610134578063340652721461012f578063378fa8fa1461012a57806343c3cb831461012557806348aa41081461012057806353a8d7391461011b578063545525f11461011657806379502c551461011157806379fa32891461010c5780637b9c9aa414610107578063a94cd93114610102578063b3b200aa146100fd578063b79a6c0c146100f8578063bba9282e146100f3578063c9b6ca9b146100ee578063ce7025e9146100e9578063d93af1d2146100e45763f490ca96146100df575f80fd5b6107a7565b610785565b61070c565b6106f0565b6106c8565b6105ea565b610552565b6104c0565b610442565b6102c4565b610254565b610237565b61021b565b6101c1565b6101a6565b61018b565b610166565b610147565b5f91031261014357565b5f80fd5b34610143575f3660031901126101435760205f5460c01c604051908152f35b34610143575f3660031901126101435760206001600160801b035f5416604051908152f35b34610143575f36600319011261014357602060405160218152f35b34610143575f36600319011261014357602060405160718152f35b34610143575f366003190112610143575f60206040516101e0816107dd565b8281520152604080516101f2816107dd565b6001600160401b0360015491828152602082600254169101908152835192835251166020820152f35b34610143575f3660031901126101435760206040516104008152f35b34610143575f366003190112610143576020600554604051908152f35b34610143575f366003190112610143576040517f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03168152602090f35b600435906001600160801b038216820361014357565b604435906001600160801b038216820361014357565b34610143576020366003190112610143576102dd610298565b33151580610382575b61037357670de0b6b3a76400006001600160801b038216116103645761035f816103457f6f864cce5237e12ffc9a99fc6c59af17222c2bbb3457690cc8753ab16b5d715e936001600160801b03166001600160801b03195f5416175f55565b6040516001600160801b0390911681529081906020820190565b0390a1005b630d62f21160e11b5f5260045ffd5b63bb62587160e01b5f5260045ffd5b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610411575f916103e2575b506001600160a01b03163314156102e6565b610404915060203d60201161040a575b6103fc81836107fd565b81019061084f565b5f6103d0565b503d6103f2565b610867565b608435906001600160401b038216820361014357565b602435906001600160401b038216820361014357565b34610143576020366003190112610143576004356001600160401b0381168103610143576104716020916108a9565b6001600160801b0360405191168152f35b6001600160a01b0381160361014357565b9181601f84011215610143578235916001600160401b038311610143576020838186019501011161014357565b346101435760e0366003190112610143576004356104dd81610482565b602435906104ea82610482565b6104f26102ae565b916064356104fe610416565b60a4359161050b83610482565b60c435956001600160401b03871161014357610538610531610550983690600401610493565b3691610909565b94604051966105486020896107fd565b5f8852610ea3565b005b34610143576101003660031901126101435760043561057081610482565b60243561057c81610482565b6105846102ae565b91606435610590610416565b9060a43561059d81610482565b60c4356001600160401b038111610143576105bc903690600401610493565b93909260e435976001600160401b038911610143576105e2610550993690600401610493565b98909761093f565b346101435760203660031901126101435760043533151580610649575b6103735761035f816106397f4f0c4dec68e1e774843a5fc3a522ab2a832ecfc975b9ad8a5033736d9e47f09d93600555565b6040519081529081906020820190565b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610411575f916106a9575b506001600160a01b0316331415610607565b6106c2915060203d60201161040a576103fc81836107fd565b5f610697565b34610143575f3660031901126101435760206001600160401b035f5460801c16604051908152f35b34610143575f36600319011261014357602060405161c3508152f35b346101435760603660031901126101435760043561072861042c565b604435916001600160401b0383116101435736602384011215610143578260040135916001600160401b038311610143573660248460051b860101116101435761077b6106399360246107819601610966565b9161159a565b0390f35b34610143575f36600319011261014357602061079f610a03565b604051908152f35b34610143575f366003190112610143576020604051670de0b6b3a76400008152f35b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b038211176107f857604052565b6107c9565b90601f801991011681019081106001600160401b038211176107f857604052565b6040519061082e610160836107fd565b565b6040519061082e610140836107fd565b6040519061082e6040836107fd565b90816020910312610143575161086481610482565b90565b6040513d5f823e3d90fd5b634e487b7160e01b5f52601160045260245ffd5b6001600160401b036001911601906001600160401b0382116108a457565b610872565b6001600160401b031661c350016001600160401b0381116108a4576001600160401b036001600160801b035f54169116026001600160801b0381169081036108a45790565b6001600160401b0381116107f857601f01601f191660200190565b929192610915826108ee565b9161092360405193846107fd565b829481845281830111610143578281602093845f960137010152565b9761095861096092939495969761082e9b993691610909565b973691610909565b96610ea3565b6001600160401b0382116107f8578160051b906040519261098a60208401856107fd565b835260208301918101903682116101435780925b8284106109ac575050505090565b83356001600160401b03811161014357820136601f82011215610143576020916109dd839236908481359101610909565b81520193019261099e565b5f198101919082116108a457565b919082039182116108a457565b6004546003549081811015610a1e5781039081116108a45790565b50505f90565b5f1981146108a45760010190565b906001600160801b03809116911601906001600160801b0382116108a457565b90816020910312610143575190565b90816020910312610143575180151581036101435790565b634e487b7160e01b5f52603260045260245ffd5b600354811015610aa95760035f52600960205f20910201905f90565b610a79565b8054821015610aa9575f52600960205f20910201905f90565b634e487b7160e01b5f525f60045260245ffd5b90600182811c92168015610b08575b6020831014610af457565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610ae9565b818110610b1d575050565b5f8155600101610b12565b9190601f8111610b3757505050565b61082e925f5260205f20906020601f840160051c83019310610b61575b601f0160051c0190610b12565b9091508190610b54565b91909182516001600160401b0381116107f857610b9281610b8c8454610ada565b84610b28565b6020601f8211600114610bd1578190610bc29394955f92610bc6575b50508160011b915f199060031b1c19161790565b9055565b015190505f80610bae565b601f19821690610be4845f5260205f2090565b915f5b818110610c1e57509583600195969710610c06575b505050811b019055565b01515f1960f88460031b161c191690555f8080610bfc565b9192602060018192868b015181550194019201610be7565b600354680100000000000000008110156107f857806001610c5c92016003556003610aae565b610de457815181546001600160a01b0319166001600160a01b0390911617815561082e916008906101409060208101516001850180546001600160a01b0319166001600160a01b039092169190911790556040810151600285015560608101516003850180546001600160a01b0319166001600160a01b03909216919091179055610d4560048501610d17610cfb60808501516001600160801b031690565b82546001600160801b0319166001600160801b03909116178255565b60a08301516001600160801b031681546001600160801b031660809190911b6001600160801b031916179055565b60c08101516005850155610dc960068501610d8a610d6d60e08501516001600160401b031690565b825467ffffffffffffffff19166001600160401b03909116178255565b6101008301516001600160a01b0316815468010000000000000000600160e01b03191660409190911b68010000000000000000600160e01b0316179055565b610ddb61012082015160078601610b6b565b01519101610b6b565b610ac7565b6001600160401b03166001600160401b0381146108a45760010190565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b6001600160a01b03918216815291811660208301526001600160801b03928316604083015292909116606082015260808101929092526001600160401b039290921660a0820152911660c082015261012060e08201819052610864939192610e9491840190610e06565b91610100818403910152610e06565b95969092949693919360018060a01b038816156111bd576104008151116111ae57610ecd8261194f565b60055461115b575b610ede836108a9565b97610ee98987610a32565b60405163868a2e9d60e01b8152979094906020896004815f60056007609a1b015af1988915610411575f9961112a575b50881561111b576040516323b872dd60e01b81523360048201523060248201526001600160801b03871660448201526001600160a01b038b16906020816064815f865af1908115610411575f916110ec575b50156110dd57803b1561014357604051630852cd8d60e31b81526001600160801b039790971660048801525f908790602490829084905af18015610411577f348c28d1410ff29393c038fe0f1998384082e98e315624b24c04a4fa6288b9de996110be9761105f926110c3575b50610fe161081e565b6001600160a01b038d1681529033602083015260408201526001600160a01b03891660608201526001600160801b038a1660808201526001600160801b038d1660a082015260c081018390526001600160401b03841660e08201526001600160a01b0385166101008201528561012082015286610140820152610c36565b5f5460801c6001600160401b03169a6110a661107a8d610de9565b5f805467ffffffffffffffff60801b191660809290921b67ffffffffffffffff60801b16919091179055565b6040519889986001600160401b03339e169c8a610e2a565b0390a3565b806110d15f6110d7936107fd565b80610139565b5f610fd8565b6312171d8360e31b5f5260045ffd5b61110e915060203d602011611114575b61110681836107fd565b810190610a61565b5f610f6b565b503d6110fc565b632968ee7f60e21b5f5260045ffd5b61114d91995060203d602011611154575b61114581836107fd565b810190610a52565b975f610f19565b503d61113b565b6007544303611197575b6006546005548110156111885761117e61118391610a24565b600655565b610ed5565b63124ab48560e11b5f5260045ffd5b6111a043600755565b6111a95f600655565b611165565b634b8a874d60e11b5f5260045ffd5b63c29f0c7160e01b5f5260045ffd5b919082018092116108a457565b9060405191825f8254926111ec84610ada565b80845293600181169081156112555750600114611211575b5061082e925003836107fd565b90505f9291925260205f20905f915b81831061123957505090602061082e928201015f611204565b6020919350806001915483858901015201910190918492611220565b90506020925061082e94915060ff191682840152151560051b8201015f611204565b90611377600861128561081e565b84546001600160a01b031681529360018101546001600160a01b031660208601526002810154604086015260038101546001600160a01b031660608601526113076112f760048301546112f16112e1826001600160801b031690565b6001600160801b031660808a0152565b60801c90565b6001600160801b031660a0870152565b600581015460c086015261135f61134e600683015461133f61132f826001600160401b031690565b6001600160401b031660e08a0152565b60401c6001600160a01b031690565b6001600160a01b0316610100870152565b61136b600782016111d9565b610120860152016111d9565b610140830152565b8051821015610aa95760209160051b010190565b604080825282516001600160a01b0316908201529291906020906114589080830151606087015260408101516001600160a01b0316608087015260608101516001600160801b031660a087015260808101516001600160801b031660c087015260a081015160e087015260c08101516001600160401b031661010087015260e08101516001600160a01b0316610120870152610120611443610100830151610140808a0152610180890190610e06565b910151868203603f1901610160880152610e06565b930152565b6114678154610ada565b9081611471575050565b81601f5f9311600114611482575055565b8183526020832061149e91601f0160051c810190600101610b12565b808252602082209081548360011b9084198560031b1c191617905555565b90610de4576008815f61082e93555f60018201555f60028201555f60038201555f60048201555f60058201555f60068201556114fa6007820161145d565b0161145d565b6003545f6003558061150f5750565b806009029060098204036108a45760035f527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b908101905b818110611552575050565b6009905f81555f60018201555f60028201555f60038201555f60048201555f60058201555f60068201556115886007820161145d565b6115946008820161145d565b01611547565b9092915f93331515806118d0575b610373576001600160401b038043169116036118c157600354906115cf60045480936109f6565b8084116118b9575b5080518381036118a25750826116af575b5050506116256116016115fc5f5460c01c90565b610886565b5f80546001600160c01b031660c09290921b6001600160c01b031916919091179055565b817fec4aff46c65f485f4b15e3c2edadda1d57d002995f5aa262a27c76b9a680ec166116aa6116555f5460c01c90565b611690611660610840565b8581526001600160401b038316602090910181905260018690556002805467ffffffffffffffff19169091179055565b6040516001600160401b0390911681529081906020820190565b0390a2565b5f199450916116be90826111cc565b91825b8281116116f857505050600455600454600354146116e2575b5f80806115e8565b6116ea611500565b6116f35f600455565b6116da565b611701816109e8565b9561170b87610a8d565b5061171590611277565b61171f85896109f6565b611729908561137f565b51806101408301519061173b916119c4565b8151602080840151604080860151905160609290921b6bffffffffffffffffffffffff191692820192835260348083019190915281526001600160a01b0390921693916117896054826107fd565b51902060608201519091906001600160a01b031660808201516001600160801b031660a08301516001600160801b031660c08401519160e08501516117d4906001600160401b031690565b6101008601519094906001600160a01b0316956101200151966117f5610830565b6001600160a01b03909a168a5260208a01526001600160a01b031660408901526001600160801b031660608801526001600160801b0316608087015260a08601526001600160401b031660c08501526001600160a01b031660e0840152610100830152610120820152604051809160208201936118729185611393565b03601f198101825261188490826107fd565b5190209561189190610a8d565b61189a916114bc565b5f19016116c1565b630db2128560e11b5f52600452602483905260445ffd5b92505f6115d7565b631391e11b60e21b5f5260045ffd5b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610411575f91611930575b506001600160a01b03163314156115a8565b611949915060203d60201161040a576103fc81836107fd565b5f61191e565b805180156119c0576021036119a257805115610aa95760208101516001600160f81b031916600160f91b81141590816119b1575b506119a257611998602161199c920151611a46565b1590565b6119a257565b6361d0136b60e11b5f5260045ffd5b600360f81b141590505f611983565b5050565b516119ed575f905b518181036119d8575050565b63521a2d4d60e11b5f5260045260245260445ffd5b6071906119cc565b3d15611a1f573d90611a06826108ee565b91611a1460405193846107fd565b82523d5f602084013e565b606090565b602081519101519060208110611a38575090565b5f199060200360031b1b1690565b80158015611b04575b611af3575f8091604051611ac981611abb602082019460076401000003d019916401000003d019906401000003d019818009090860208087528087018190526040870152606086015263800001e9600160ff1b0360808601526401000003d01960a086015260c0850190565b03601f1981018352826107fd565b519060055afa611ad76119f5565b90158015611af8575b611af357611aef600191611a24565b1490565b505f90565b50602081511415611ae0565b506401000003d019811015611a4f56fea2646970667358221220c507a58923eeb01609f13c1e26604cbb46eaf7befa4f49f7c8ce5aca93e940d264736f6c634300081e0033" + "code": "0x60806040526004361015610011575f80fd5b5f3560e01c80632c37826e14610144578063340652721461013f578063378fa8fa1461013a57806343c3cb831461013557806348aa41081461013057806353a8d7391461012b578063545525f11461012657806379502c551461012157806379fa32891461011c5780637b9c9aa414610117578063a94cd93114610112578063b3b200aa1461010d578063b79a6c0c14610108578063bba9282e14610103578063c9b6ca9b146100fe578063ce7025e9146100f9578063d93af1d2146100f4578063e2e3ee5c146100ef5763f490ca96146100ea575f80fd5b610917565b6107cd565b6107ab565b610732565b610716565b6106ee565b610610565b610578565b6104e6565b610468565b6102ea565b610264565b610247565b61022b565b6101d1565b6101b6565b61019b565b610176565b610157565b5f91031261015357565b5f80fd5b34610153575f3660031901126101535760205f5460c01c604051908152f35b34610153575f3660031901126101535760206001600160801b035f5416604051908152f35b34610153575f36600319011261015357602060405160218152f35b34610153575f36600319011261015357602060405160718152f35b34610153575f366003190112610153575f60206040516101f08161094d565b8281520152604080516102028161094d565b6001600160401b0360015491828152602082600254169101908152835192835251166020820152f35b34610153575f3660031901126101535760206040516104008152f35b34610153575f366003190112610153576020600554604051908152f35b34610153575f366003190112610153576040517f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03168152602090f35b600435906001600160801b038216820361015357565b604435906001600160801b038216820361015357565b602435906001600160801b038216820361015357565b34610153576020366003190112610153576103036102a8565b331515806103a8575b61039957670de0b6b3a76400006001600160801b0382161161038a576103858161036b7f6f864cce5237e12ffc9a99fc6c59af17222c2bbb3457690cc8753ab16b5d715e936001600160801b03166001600160801b03195f5416175f55565b6040516001600160801b0390911681529081906020820190565b0390a1005b630d62f21160e11b5f5260045ffd5b63bb62587160e01b5f5260045ffd5b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610437575f91610408575b506001600160a01b031633141561030c565b61042a915060203d602011610430575b610422818361096d565b8101906109bf565b5f6103f6565b503d610418565b6109d7565b608435906001600160401b038216820361015357565b602435906001600160401b038216820361015357565b34610153576020366003190112610153576004356001600160401b038116810361015357610497602091610a19565b6001600160801b0360405191168152f35b6001600160a01b0381160361015357565b9181601f84011215610153578235916001600160401b038311610153576020838186019501011161015357565b346101535760e036600319011261015357600435610503816104a8565b60243590610510826104a8565b6105186102be565b9160643561052461043c565b60a43591610531836104a8565b60c435956001600160401b0387116101535761055e6105576105769836906004016104b9565b3691610a79565b946040519661056e60208961096d565b5f8852611027565b005b346101535761010036600319011261015357600435610596816104a8565b6024356105a2816104a8565b6105aa6102be565b916064356105b661043c565b9060a4356105c3816104a8565b60c4356001600160401b038111610153576105e29036906004016104b9565b93909260e435976001600160401b038911610153576106086105769936906004016104b9565b989097610ac3565b34610153576020366003190112610153576004353315158061066f575b610399576103858161065f7f4f0c4dec68e1e774843a5fc3a522ab2a832ecfc975b9ad8a5033736d9e47f09d93600555565b6040519081529081906020820190565b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610437575f916106cf575b506001600160a01b031633141561062d565b6106e8915060203d60201161043057610422818361096d565b5f6106bd565b34610153575f3660031901126101535760206001600160401b035f5460801c16604051908152f35b34610153575f36600319011261015357602060405161c3508152f35b346101535760603660031901126101535760043561074e610452565b604435916001600160401b0383116101535736602384011215610153578260040135916001600160401b038311610153573660248460051b86010111610153576107a161065f9360246107a79601610aea565b9161171e565b0390f35b34610153575f3660031901126101535760206107c5610b87565b604051908152f35b34610153576060366003190112610153576004356107ea816104a8565b6107f26102d4565b906044356107ff816104a8565b33151580610898575b610399576105769261084e61085e9261083161082261098e565b6001600160a01b039096168652565b5f6020860181905260408601526001600160a01b03166060850152565b6001600160801b03166080830152565b5f60a08201525f60c08201525f60e08201525f61010082015261087f610aaf565b61012082015261088d610aaf565b610140820152610d65565b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610437575f916108f8575b506001600160a01b0316331415610808565b610911915060203d60201161043057610422818361096d565b5f6108e6565b34610153575f366003190112610153576020604051670de0b6b3a76400008152f35b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b0382111761096857604052565b610939565b90601f801991011681019081106001600160401b0382111761096857604052565b6040519061099e6101608361096d565b565b6040519061099e6101408361096d565b6040519061099e60408361096d565b9081602091031261015357516109d4816104a8565b90565b6040513d5f823e3d90fd5b634e487b7160e01b5f52601160045260245ffd5b6001600160401b036001911601906001600160401b038211610a1457565b6109e2565b6001600160401b031661c350016001600160401b038111610a14576001600160401b036001600160801b035f54169116026001600160801b038116908103610a145790565b6001600160401b03811161096857601f01601f191660200190565b929192610a8582610a5e565b91610a93604051938461096d565b829481845281830111610153578281602093845f960137010152565b60405190610abe60208361096d565b5f8252565b97610adc610ae492939495969761099e9b993691610a79565b973691610a79565b96611027565b6001600160401b038211610968578160051b9060405192610b0e602084018561096d565b835260208301918101903682116101535780925b828410610b30575050505090565b83356001600160401b03811161015357820136601f8201121561015357602091610b61839236908481359101610a79565b815201930192610b22565b5f19810191908211610a1457565b91908203918211610a1457565b6004546003549081811015610ba2578103908111610a145790565b50505f90565b634e487b7160e01b5f52603260045260245ffd5b600354811015610bd85760035f52600960205f20910201905f90565b610ba8565b8054821015610bd8575f52600960205f20910201905f90565b634e487b7160e01b5f525f60045260245ffd5b90600182811c92168015610c37575b6020831014610c2357565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610c18565b818110610c4c575050565b5f8155600101610c41565b9190601f8111610c6657505050565b61099e925f5260205f20906020601f840160051c83019310610c90575b601f0160051c0190610c41565b9091508190610c83565b91909182516001600160401b03811161096857610cc181610cbb8454610c09565b84610c57565b6020601f8211600114610d00578190610cf19394955f92610cf5575b50508160011b915f199060031b1c19161790565b9055565b015190505f80610cdd565b601f19821690610d13845f5260205f2090565b915f5b818110610d4d57509583600195969710610d35575b505050811b019055565b01515f1960f88460031b161c191690555f8080610d2b565b9192602060018192868b015181550194019201610d16565b6003546801000000000000000081101561096857806001610d8b92016003556003610bdd565b610f1357815181546001600160a01b0319166001600160a01b0390911617815561099e916008906101409060208101516001850180546001600160a01b0319166001600160a01b039092169190911790556040810151600285015560608101516003850180546001600160a01b0319166001600160a01b03909216919091179055610e7460048501610e46610e2a60808501516001600160801b031690565b82546001600160801b0319166001600160801b03909116178255565b60a08301516001600160801b031681546001600160801b031660809190911b6001600160801b031916179055565b60c08101516005850155610ef860068501610eb9610e9c60e08501516001600160401b031690565b825467ffffffffffffffff19166001600160401b03909116178255565b6101008301516001600160a01b0316815468010000000000000000600160e01b03191660409190911b68010000000000000000600160e01b0316179055565b610f0a61012082015160078601610c9a565b01519101610c9a565b610bf6565b5f198114610a145760010190565b906001600160801b03809116911601906001600160801b038211610a1457565b90816020910312610153575190565b90816020910312610153575180151581036101535790565b6001600160401b03166001600160401b038114610a145760010190565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b6001600160a01b03918216815291811660208301526001600160801b03928316604083015292909116606082015260808101929092526001600160401b039290921660a0820152911660c082015261012060e082018190526109d493919261101891840190610f8a565b91610100818403910152610f8a565b95969092949693919360018060a01b03881615611341576104008151116113325761105182611ad3565b6005546112df575b61106283610a19565b9761106d8987610f26565b60405163868a2e9d60e01b8152979094906020896004815f60056007609a1b015af1988915610437575f996112ae575b50881561129f576040516323b872dd60e01b81523360048201523060248201526001600160801b03871660448201526001600160a01b038b16906020816064815f865af1908115610437575f91611270575b501561126157803b1561015357604051630852cd8d60e31b81526001600160801b039790971660048801525f908790602490829084905af18015610437577f348c28d1410ff29393c038fe0f1998384082e98e315624b24c04a4fa6288b9de99611242976111e392611247575b5061116561098e565b6001600160a01b038d1681529033602083015260408201526001600160a01b03891660608201526001600160801b038a1660808201526001600160801b038d1660a082015260c081018390526001600160401b03841660e08201526001600160a01b0385166101008201528561012082015286610140820152610d65565b5f5460801c6001600160401b03169a61122a6111fe8d610f6d565b5f805467ffffffffffffffff60801b191660809290921b67ffffffffffffffff60801b16919091179055565b6040519889986001600160401b03339e169c8a610fae565b0390a3565b806112555f61125b9361096d565b80610149565b5f61115c565b6312171d8360e31b5f5260045ffd5b611292915060203d602011611298575b61128a818361096d565b810190610f55565b5f6110ef565b503d611280565b632968ee7f60e21b5f5260045ffd5b6112d191995060203d6020116112d8575b6112c9818361096d565b810190610f46565b975f61109d565b503d6112bf565b600754430361131b575b60065460055481101561130c5761130261130791610f18565b600655565b611059565b63124ab48560e11b5f5260045ffd5b61132443600755565b61132d5f600655565b6112e9565b634b8a874d60e11b5f5260045ffd5b63c29f0c7160e01b5f5260045ffd5b91908201809211610a1457565b9060405191825f82549261137084610c09565b80845293600181169081156113d95750600114611395575b5061099e9250038361096d565b90505f9291925260205f20905f915b8183106113bd57505090602061099e928201015f611388565b60209193508060019154838589010152019101909184926113a4565b90506020925061099e94915060ff191682840152151560051b8201015f611388565b906114fb600861140961098e565b84546001600160a01b031681529360018101546001600160a01b031660208601526002810154604086015260038101546001600160a01b0316606086015261148b61147b6004830154611475611465826001600160801b031690565b6001600160801b031660808a0152565b60801c90565b6001600160801b031660a0870152565b600581015460c08601526114e36114d260068301546114c36114b3826001600160401b031690565b6001600160401b031660e08a0152565b60401c6001600160a01b031690565b6001600160a01b0316610100870152565b6114ef6007820161135d565b6101208601520161135d565b610140830152565b8051821015610bd85760209160051b010190565b604080825282516001600160a01b0316908201529291906020906115dc9080830151606087015260408101516001600160a01b0316608087015260608101516001600160801b031660a087015260808101516001600160801b031660c087015260a081015160e087015260c08101516001600160401b031661010087015260e08101516001600160a01b03166101208701526101206115c7610100830151610140808a0152610180890190610f8a565b910151868203603f1901610160880152610f8a565b930152565b6115eb8154610c09565b90816115f5575050565b81601f5f9311600114611606575055565b8183526020832061162291601f0160051c810190600101610c41565b808252602082209081548360011b9084198560031b1c191617905555565b90610f13576008815f61099e93555f60018201555f60028201555f60038201555f60048201555f60058201555f600682015561167e600782016115e1565b016115e1565b6003545f600355806116935750565b80600902906009820403610a145760035f527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b908101905b8181106116d6575050565b6009905f81555f60018201555f60028201555f60038201555f60048201555f60058201555f600682015561170c600782016115e1565b611718600882016115e1565b016116cb565b9092915f9333151580611a54575b610399576001600160401b03804316911603611a4557600354906117536004548093610b7a565b808411611a3d575b508051838103611a26575082611833575b5050506117a96117856117805f5460c01c90565b6109f6565b5f80546001600160c01b031660c09290921b6001600160c01b031916919091179055565b817fec4aff46c65f485f4b15e3c2edadda1d57d002995f5aa262a27c76b9a680ec1661182e6117d95f5460c01c90565b6118146117e46109b0565b8581526001600160401b038316602090910181905260018690556002805467ffffffffffffffff19169091179055565b6040516001600160401b0390911681529081906020820190565b0390a2565b5f199450916118429082611350565b91825b82811161187c5750505060045560045460035414611866575b5f808061176c565b61186e611684565b6118775f600455565b61185e565b61188581610b6c565b9561188f87610bbc565b50611899906113fb565b6118a38589610b7a565b6118ad9085611503565b5180610140830151906118bf91611b48565b8151602080840151604080860151905160609290921b6bffffffffffffffffffffffff191692820192835260348083019190915281526001600160a01b03909216939161190d60548261096d565b51902060608201519091906001600160a01b031660808201516001600160801b031660a08301516001600160801b031660c08401519160e0850151611958906001600160401b031690565b6101008601519094906001600160a01b0316956101200151966119796109a0565b6001600160a01b03909a168a5260208a01526001600160a01b031660408901526001600160801b031660608801526001600160801b0316608087015260a08601526001600160401b031660c08501526001600160a01b031660e0840152610100830152610120820152604051809160208201936119f69185611517565b03601f1981018252611a08908261096d565b51902095611a1590610bbc565b611a1e91611640565b5f1901611845565b630db2128560e11b5f52600452602483905260445ffd5b92505f61175b565b631391e11b60e21b5f5260045ffd5b50604051630b83774760e31b81526020816004817f0000000000000000000000001c000000000000000000000000000000000000036001600160a01b03165afa908115610437575f91611ab4575b506001600160a01b031633141561172c565b611acd915060203d60201161043057610422818361096d565b5f611aa2565b80518015611b4457602103611b2657805115610bd85760208101516001600160f81b031916600160f91b8114159081611b35575b50611b2657611b1c6021611b20920151611bca565b1590565b611b2657565b6361d0136b60e11b5f5260045ffd5b600360f81b141590505f611b07565b5050565b51611b71575f905b51818103611b5c575050565b63521a2d4d60e11b5f5260045260245260445ffd5b607190611b50565b3d15611ba3573d90611b8a82610a5e565b91611b98604051938461096d565b82523d5f602084013e565b606090565b602081519101519060208110611bbc575090565b5f199060200360031b1b1690565b80158015611c88575b611c77575f8091604051611c4d81611c3f602082019460076401000003d019916401000003d019906401000003d019818009090860208087528087018190526040870152606086015263800001e9600160ff1b0360808601526401000003d01960a086015260c0850190565b03601f19810183528261096d565b519060055afa611c5b611b79565b90158015611c7c575b611c7757611c73600191611ba8565b1490565b505f90565b50602081511415611c64565b506401000003d019811015611bd356fea2646970667358221220eb80a77022ec23ed3e41592432773382bd8fc97d603a9b06567317d40465ff5064736f6c634300081e0033" }, "0x1c00000000000000000000000000000000000003": { "nonce": "0x1", "balance": "0x0", - "code": "0x6080806040526004361015610012575f80fd5b5f3560e01c9081631beb1ab814610561575080631fbb25ad1461051d5780633488ce0d146102dd5780635c1bba381461023b5780636d46e98714610193578063a21de6d91461014f5763e202d99514610069575f80fd5b34610138575f366003190112610138576040516381e3da6b60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260016024830152602090829060449082907f0000000000000000000000001c00000000000000000000000000000000000000165afa8015610144575f9061010d575b6040516001600160a01b039091168152602090f35b506020813d60201161013c575b816101276020938361067c565b8101031261013857602090516100f8565b5f80fd5b3d915061011a565b6040513d5f823e3d90fd5b34610138575f366003190112610138576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610138576020366003190112610138576004356001600160a01b0381169081900361013857604051630b83774760e31b8152602081600481305afa908115610144575f916101f6575b506040516001600160a01b039091169091148152602090f35b90506020813d602011610233575b816102116020938361067c565b810103126101385751906001600160a01b0382168203610138579060206101dd565b3d9150610204565b34610138575f366003190112610138576040516381e3da6b60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301525f6024830152602090829060449082907f0000000000000000000000001c00000000000000000000000000000000000000165afa8015610144575f9061010d576040516001600160a01b039091168152602090f35b34610138575f366003190112610138576040516381e3da6b60e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b038181166004840152600660248401527f0000000000000000000000001c00000000000000000000000000000000000000169190602082604481865afa918215610144575f926104e9575b5081156104da576040516020810190600682526020815261038f60408261067c565b519020915f1981019081116104c6578060011b90808204600214901517156104c65782018092116104c65760018201908183116104c6576040516381e3da6b60e01b81526001600160a01b03821660048201526024810193909352602083604481875afa928315610144575f9361048e575b506040516381e3da6b60e01b81526001600160a01b03909116600482015260248101919091529160209083908180604481015b03915afa918215610144575f92610459575b5060ff6040928351928352166020820152f35b91506020823d602011610486575b816104746020938361067c565b810103126101385790519060ff610446565b3d9150610467565b919092506020823d6020116104be575b816104ab6020938361067c565b8101031261013857905191610434610401565b3d915061049e565b634e487b7160e01b5f52601160045260245ffd5b630c322fb560e31b5f5260045ffd5b9091506020813d602011610515575b816105056020938361067c565b810103126101385751908361036d565b3d91506104f8565b34610138575f366003190112610138576040517f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b03168152602090f35b34610138576020366003190112610138576004356001600160a01b0381169190829003610138576105fe9181602080930191825260076040820152604081526105ab60608261067c565b5190206040516381e3da6b60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166004820152602481019190915291829081906044820190565b03817f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b03165afa8015610144575f90610649575b60209060ff604051911615158152f35b506020813d602011610674575b816106636020938361067c565b810103126101385760209051610639565b3d9150610656565b90601f8019910116810190811067ffffffffffffffff82111761069e57604052565b634e487b7160e01b5f52604160045260245ffdfea26469706673582212202123abc3d91c41a1be59b6f06bfc92259b93aa367f581f04eda761e4ed25c63c64736f6c634300081e0033" + "code": "0x6080806040526004361015610012575f80fd5b5f3560e01c9081631beb1ab814610561575080631fbb25ad1461051d5780633488ce0d146102dd5780635c1bba381461023b5780636d46e98714610193578063a21de6d91461014f5763e202d99514610069575f80fd5b34610138575f366003190112610138576040516381e3da6b60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260016024830152602090829060449082907f0000000000000000000000001c00000000000000000000000000000000000000165afa8015610144575f9061010d575b6040516001600160a01b039091168152602090f35b506020813d60201161013c575b816101276020938361067c565b8101031261013857602090516100f8565b5f80fd5b3d915061011a565b6040513d5f823e3d90fd5b34610138575f366003190112610138576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610138576020366003190112610138576004356001600160a01b0381169081900361013857604051630b83774760e31b8152602081600481305afa908115610144575f916101f6575b506040516001600160a01b039091169091148152602090f35b90506020813d602011610233575b816102116020938361067c565b810103126101385751906001600160a01b0382168203610138579060206101dd565b3d9150610204565b34610138575f366003190112610138576040516381e3da6b60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301525f6024830152602090829060449082907f0000000000000000000000001c00000000000000000000000000000000000000165afa8015610144575f9061010d576040516001600160a01b039091168152602090f35b34610138575f366003190112610138576040516381e3da6b60e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b038181166004840152600660248401527f0000000000000000000000001c00000000000000000000000000000000000000169190602082604481865afa918215610144575f926104e9575b5081156104da576040516020810190600682526020815261038f60408261067c565b519020915f1981019081116104c6578060011b90808204600214901517156104c65782018092116104c65760018201908183116104c6576040516381e3da6b60e01b81526001600160a01b03821660048201526024810193909352602083604481875afa928315610144575f9361048e575b506040516381e3da6b60e01b81526001600160a01b03909116600482015260248101919091529160209083908180604481015b03915afa918215610144575f92610459575b5060ff6040928351928352166020820152f35b91506020823d602011610486575b816104746020938361067c565b810103126101385790519060ff610446565b3d9150610467565b919092506020823d6020116104be575b816104ab6020938361067c565b8101031261013857905191610434610401565b3d915061049e565b634e487b7160e01b5f52601160045260245ffd5b630c322fb560e31b5f5260045ffd5b9091506020813d602011610515575b816105056020938361067c565b810103126101385751908361036d565b3d91506104f8565b34610138575f366003190112610138576040517f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b03168152602090f35b34610138576020366003190112610138576004356001600160a01b0381169190829003610138576105fe9181602080930191825260076040820152604081526105ab60608261067c565b5190206040516381e3da6b60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166004820152602481019190915291829081906044820190565b03817f0000000000000000000000001c000000000000000000000000000000000000006001600160a01b03165afa8015610144575f90610649575b60209060ff604051911615158152f35b506020813d602011610674575b816106636020938361067c565b810103126101385760209051610639565b3d9150610656565b90601f8019910116810190811067ffffffffffffffff82111761069e57604052565b634e487b7160e01b5f52604160045260245ffdfea26469706673582212201c909c199411f678d91cc09085bac7c80d3458f7269a4687d397f586482f06e964736f6c634300081e0033" }, "0x1c00000000000000000000000000000000000004": { "nonce": "0x1",