feat(voting): BSC BEP20 CL8Y ledger + EVM wallet voting (core electorate) #588
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:implement
agent:implement
agent:open_issues
agent:ready
agent:research
agent:security_audit
agent:verify
architecture
backend
blocker:hybrid
blocker:launch
blocker:limit-orders
blocker:v2
block:log_only
block:security
bug
ci
contracts
correctness
deploy
dev
devops
docs
documentation
duplicate
e2e
enhancement
epic
feature
frontend
functional-completion
gas
good first issue
governance
help wanted
high-risk
hooks
hybrid
indexer
infra
infrastructure
integrators
invalid
launch-blocker
limit-orders
localnet
localterra
low priority
missing-implementation
needs-design
ops
performance
priority
high
priority
medium
product
qa
QA
question
ready
ready
research
scripts
security
security-hardening
smartcontracts
tech-debt
testing
ux
UX
v2
verification
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/cl8y-dex-terraclassic#588
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
BSC is core to the voting electorate, not an optional extra. A majority of CL8Y holders are on BNB Smart Chain (BEP-20), not Terra Classic CW20. Shipping #509 / #510 / #511 as Terra-only would exclude most tokenholders from registration, proposal weight, and ballots.
Extend the offchain snapshot-voting bundle so that:
balanceOfat registration + Transfer logs forward — same “no archive node” model as #509).operator-votingaccepts EVM wallet signatures (EIP-191personal_sign) for register / propose / vote, and freezes vote power from both the Terra CW20 ledger and the BSC BEP-20 ledger./voteflows.No new Solidity or CosmWasm contracts. Frontend + Postgres + indexer +
operator-votingonly.BEP-20 CL8Y (canonical BSC):
0x8F452a1fdd388A45e1080992eFF051b4dd9048d2(CL8Y_v2, 18 decimals) — same asset brand as Terra CW20terra16wtml…hpax3. Configurable via env (BSC_CL8Y_TOKEN_ADDRESS).Terra CW20 (unchanged, #509):
terra16wtml2q66g82fdkx66tap0qjkahqwp4lwq3ngtygacg5q0kzycgqvhpax3.This issue is the cross-chain / EVM work item. It does not replace #509–#511; those issues must include BSC in their scope (see comments on each).
Bundle
operator-voting— Cosmos ADR-36 and EVM EIP-191 sigs; snapshot = Terra height plus BSC block; blacklist includes0xaddressesWhy this is needed
#509–#511 currently assume a Terra Classic wallet + CW20
Balance+ wasm transfer events. That is correct for the DEX’s home chain and for fee-discountcl8y_token, but it is not the majority CL8Y holder set.Without BSC:
Venus
eth_callonBSC_RPC_URLS(#571) already proves the indexer can talk to BSC JSON-RPC. That path is oracle-only and must not be overloaded. Voting needs a separate BEP-20 ledger + EVM auth plane.Current codebase
indexer/src/indexer/venus_vfdusd.rs+config.bsc_rpc_urls(BSC_RPC_URLS) — Venus vFDUSDeth_callonly. Noeth_getLogs, no ERC-20balanceOf, no Transfer parserVITE_*BSC RPC, no BscScan from the dApp. Wallet provider connect for signing is a new surfacefrontend-dapp/src/services/terraclassic/wallet.ts). WalletConnect is EIP-155 Cosmos pairing (#519 / #554 / #566), not BSChttps://terms.cl8y.com/sign/evm(#517 clickwrap) — external redirect, not in-app MetaMask; do not reuse as voting authoperator-voting/votesignArbitraryConstraints / guardrails
balanceOf(wallet)at currenteth_blockNumber. History afterward = Transfer logs for the registered set only (mirror #509).balanceOffor configuredBSC_CL8Y_TOKEN_ADDRESS(default0x8F452a1fdd388A45e1080992eFF051b4dd9048d2). Ignore other BEP-20s and lookalike tickers.NUMERIC— same as CW20; no float.fromortois a registered EVM address (plus the registered counterparty). Do not ingest the full CL8Y holder universe.BSC_RPC_URLStransport, not the Venus module. New indexer module (e.g.bsc_cl8y_ledger.rs). EmptyBSC_RPC_URLSskips live BSC (CI/LocalTerra) the same way #571 does. Never log RPC URLs/keys. Soft-fail RPC must not invent balances.eth_call/eth_getLogs. Injected/WC provider is only for connect +personal_sign.terra1…registration and a0x…registration are distinct voters unless product later adds explicit linking. Do not silently merge by heuristic.VOTING_BLACKLIST_ADDRESSES) must accept normalized0x(EIP-55 checksum optional; compare case-insensitive) and Terra bech32.venus_vfdusd_rates.trader_positions, or PancakeSwap LP as vote weight.Relevant files
Indexer / BSC I/O
indexer/src/config.rs(bsc_rpc_urls)indexer/src/indexer/venus_vfdusd.rs(RPC failover /eth_callpattern — do not overload)indexer/src/startup.rs,indexer/src/lcd/mod.rs(Terra live balance analogue)indexer/migrations/,docs/indexer-invariants.mdbalanceOfregistration ingest + BSC height/block cursoroperator-voting (#510)
ecrecoveroverkeccak256("\x19Ethereum Signed Message:\n" + len + message)), chain-id / domain separation, EVM address normalizevoting_bsc_cl8y_balance_at(wallet, block)beside Terravoting_cl8y_balance_atFrontend (#511)
frontend-dapp/src/services/terraclassic/wallet.ts,hooks/useWallet.ts, WalletConnect pairing stores (#554)frontend-dapp/src/utils/legalClickwrap.ts(Legal EVM portal is not voting)personal_signhelper;/votecopy that Terra or BSC holders can registerAGENTS_FRONTEND_WALLETCONNECT_MOBILE.md,AGENTS_FRONTEND_COPY_COGNITIVE_LOAD.md,AGENTS_INDEXER_VENUS_VFDUSD.md(RPC hygiene)Env / deploy
BSC_RPC_URLS(existing),BSC_CL8Y_TOKEN_ADDRESS, Coolify indexer +operator-voting+ frontend examplesVITE_*must not include BSC RPC URLsRecommended direction
Indexer (extends #509)
voting_registrationsgainschain(terra|bsc) +address;cl8y_bep20_transfers(bsc_block, tx_hash, log_index, from, to, amount);cl8y_bsc_balancescheckpoints forbalance(wallet, bsc_block)whenblock >= registered_at_block.eth_blockNumber+eth_callbalanceOf(address)on pinned CL8Y; persist; no historicaleth_getLogsbackfill unless explicitly designed (default no backfill, same as #509).eth_getLogsfor Transfer topic0xddf252ad…on the pinned token; filter to registered set; handle mint/burn (from/tozero address).indexer_state.operator-voting (extends #510)
chain/ recovered address.{ terra_height, bsc_block, created_at }.Frontend (extends #511)
eip155:56).Acceptance criteria
balanceOf+ current BSC block; no archive/debug_tracerequirement.balance(evm, B)forB >= registered_at_blockis reconstructible from the ledger; property/integration tested with fixtures (wiremock / Anvil — not live mainnet).operator-votingaccepts EIP-191 register / propose / vote from the recovered0xaddress; Terra ADR-36 path still works.0xcannot vote or propose.VITE_*BSC RPC; no Venus poller reuse; docs/invariants/Coolify env updated.Test plan (all paths)
from/to.v/ replayed Terra payload.balanceOfat block N; row matches.BSC_RPC_URLSskips BSC ledger when feature optional in CI; production voting compose requires it.Test plan — attack, hack & abuse vectors
BSC_RPC_URLSremains env-only (existing I389-18 class); do not take RPC URL from client.0xabc…vs0xAbC…must be one wallet; blacklist bypass via case must fail.Verification criteria
operator-votingtests for EIP-191 + mixed Terra/EVM blacklist + dual snapshot fields.docs/indexer-invariants.md+ Coolify env; skill notes that voting BSC I/O ≠ Venus.Labels
architecturebackendfrontendindexerenhancementsecurityproductUXPriority
P1 — core electorate. Majority of CL8Y is BEP-20 on BSC.
marked as related to #509
marked as related to #510
marked as related to #511
mentioned in issue #509
mentioned in issue #510
mentioned in issue #511
Voting work left this repo on 2026-08-25.
Canonical project: https://gitlab.com/PlasticDigits/voting
Also opened there: Legal clickwrap (#5), wallet reuse (#6). Do not implement voting in this DEX repo.
mentioned in issue #637