571c5f9261
Task A, static phase. Ghidra 12.1.2 headless via the repo's own pyghidra harness
over CardsDLL_Win64_retail.dll (13,382 functions). Queries and raw decompiler
output committed under docs/evidence/market-sold-re-2026-08-17/.
RECOVERED FROM THE BINARY
1. No sold token, now EXHAUSTIVELY: both vocabularies dumped to their sentinels
rather than sampled. tradeState is exactly 4 rows; itemState is exactly 12
(invalid/free/WAITING_FOR_GAME/inGame/forSale/offered/activeBadge/
activeHomeKit/activeAwayKit/activeBall/activeStadium/active=255). A sold row
MUST therefore be a combination of existing atoms.
2. What closed does, complete, from the auctionInfo deserializer 0x18013e410:
IS_GLOW = (tradeState==closed) ? bidState != none
: bidState in {outbid, buyNow}
INBOX = bidState in {highest, buyNow}
3. The full record -> Flash map from the publisher 0x1801bf030, superseding the
partial list. The prize: record +0xbf is published as COINS_AWARDED, fed by the
coinsProcessed atom 0x2f4. The corpus had recorded that atom's type and noted
its consumer was never found; it is now traced. DURATION also renders the
localised FUT_AUCTION_EXPIRED when expires underflows.
4. highest vs buyNow on a closed row is UNDECIDABLE from CardsDLL, by proof: both
yield IS_GLOW=1/INBOX=1, bit-identical. But bidState is ALSO published verbatim
as YOURBID alongside STATE and COINS_AWARDED, so the movie does receive the raw
values - the discrimination exists and lives entirely in unread ActionScript.
This retires the question as a static target, and it contradicts the
third-party lore that a seller's sold row is closed+buyNow (the corpus's own
lifecycle table says closed+highest and assigns buyNow to the buyer).
5. The clear-sold verb EXISTS. Builder 0x1801647c0 emits "/sold" when the tradeId
field is zero and "/%lld" otherwise, on route base ut/delete/%s/trade, response
class RS4 FutISRemoveTradeServerResponse. Confirmed by the client's own
request-name table entry RemoveAllSoldFromTradePile. A BULK clear-sold verb only
makes sense if sold rows PERSIST in the seller's pile until cleared, which is
incompatible with our Fix A invariant - so the sold path will require revisiting
it under live validation.
6. The seller's SOLD counter is real, proven end to end with no inference: the hub
tradePile sub-deserializer 0x18013ead0 writes atom sold 0x2c9 to +0x1d8, and the
tile publisher 0x1800b1dc0 renders +0x1d8 as Flash TEXT3 under the localised
caption FUT_TF_SOLD. Siblings: selling -> +0x1d2 -> FUT_TF_SELLING,
count -> +0x1d4 -> FUT_UC_ITEMS, plus FUT_TF_WINNING/FUT_TF_OUTBID on the
Transfer Targets tile. We and the Python oracle both hardcode sold:0, so that
bucket can never fill.
7. Reusable method: an atom id is the INDEX into the alphabetical atom-name pointer
table at base 0x1802d2760. Validated 12/12 against the known auctionInfo atoms
and cross-checked against fifa17-recon/docs/fut_atoms.tsv. Documented gotcha:
resolve a name by the pointer slot INSIDE the table, never by the first matching
string in the binary, or you get confident nonsense.
8. An auction-outcome vocabulary exists (auctionSoldBid 0x39, auctionSoldBuyNow
0x3a, auctionWon*/auctionLost*) but NO deserializer consumes it - every
candidate function was checked for the value-SKIP/atom-loop signature and none
qualifies. Server-side or telemetry only; it does not carry sold state here.
TASK B IS UNDECIDABLE FROM THE CLIENT, and this is a proof of absence: no 0.95 or
0.05 constant of either width, no tax/fee/net/proceeds caption, and no fee
arithmetic anywhere. The client never computes or displays a net, so no experiment
against our own server can measure the rounding - whatever we credit is what it
displays, and there is no oracle. Only an original EA-era seller-balance capture
could settle it. The rule stays an explicit CHOICE (floor the fee, so
fee + proceeds == gross exactly) and is now pinned at the requested boundaries
100/101/119/120/149/150/151/199/200 plus 15,000 and i64::MAX.
Settlement NOT promoted. No production process, port or database was touched.
309 lines
10 KiB
Plaintext
309 lines
10 KiB
Plaintext
==============================================================================
|
|
== auctionInfo deserializer 0x18013e410 — full decompilation
|
|
==============================================================================
|
|
|
|
/* WARNING: Function: __security_check_cookie replaced with injection: security_check_cookie */
|
|
|
|
undefined4 FUN_18013e410(undefined8 param_1,longlong param_2,undefined8 param_3)
|
|
|
|
{
|
|
longlong *plVar1;
|
|
undefined1 *puVar2;
|
|
undefined1 *puVar3;
|
|
undefined ***pppuVar4;
|
|
undefined ***pppuVar5;
|
|
char cVar6;
|
|
int iVar7;
|
|
int iVar8;
|
|
undefined8 uVar9;
|
|
longlong *plVar10;
|
|
undefined4 uVar11;
|
|
undefined1 auStack_138 [32];
|
|
undefined **local_118;
|
|
undefined8 local_110;
|
|
longlong local_108;
|
|
undefined8 local_100;
|
|
undefined **local_f8;
|
|
undefined1 local_f0 [32];
|
|
undefined1 local_d0;
|
|
longlong *local_c8;
|
|
undefined8 local_c0;
|
|
undefined1 local_b0 [36];
|
|
undefined4 local_8c;
|
|
undefined4 local_88;
|
|
undefined4 local_84;
|
|
undefined4 local_80;
|
|
int local_70;
|
|
undefined8 local_68;
|
|
undefined1 local_58 [8];
|
|
longlong local_50;
|
|
longlong *local_48;
|
|
int local_40;
|
|
undefined1 local_3c;
|
|
undefined1 local_3b;
|
|
undefined1 local_3a;
|
|
undefined1 local_39;
|
|
ulonglong local_38;
|
|
|
|
local_100 = 0xfffffffffffffffe;
|
|
local_38 = DAT_1802db6e0 ^ (ulonglong)auStack_138;
|
|
iVar8 = 0x38c;
|
|
FUN_18010f5f0(&local_f8);
|
|
iVar7 = FUN_1801c7f10(param_2);
|
|
while (iVar7 != 10) {
|
|
if (*(int *)(param_2 + 0xd0) == 0xb) {
|
|
iVar8 = FUN_180180d00(*(undefined8 *)(param_2 + 0xf8));
|
|
iVar7 = FUN_1801c7f10(param_2);
|
|
if (iVar7 != 6) goto LAB_18013e498;
|
|
}
|
|
else {
|
|
LAB_18013e498:
|
|
if (iVar8 < 0x2b8) {
|
|
if (iVar8 == 0x2b7) {
|
|
uVar9 = FUN_1801c7aa0(param_2);
|
|
FUN_180008120(local_b0,uVar9,0x1e);
|
|
}
|
|
else if (iVar8 < 0x117) {
|
|
if (iVar8 == 0x116) {
|
|
local_68 = FUN_1801c79d0(param_2);
|
|
}
|
|
else if (iVar8 == 0x57) {
|
|
uVar9 = FUN_1801c7aa0(param_2);
|
|
local_40 = FUN_180166380(uVar9);
|
|
}
|
|
else if (iVar8 == 0x65) {
|
|
uVar9 = FUN_1801c79d0(param_2);
|
|
local_88 = FUN_1800d7b30(uVar9);
|
|
}
|
|
else {
|
|
if (iVar8 != 0xc1) goto LAB_18013e59b;
|
|
uVar9 = FUN_1801c79d0(param_2);
|
|
local_80 = FUN_1800d7b30(uVar9);
|
|
}
|
|
}
|
|
else if (iVar8 == 0x16b) {
|
|
FUN_18013fe00(local_58,param_2,0);
|
|
}
|
|
else if (iVar8 == 0x2b6) {
|
|
uVar9 = FUN_1801c79d0(param_2);
|
|
local_8c = FUN_1800d7b30(uVar9);
|
|
}
|
|
else {
|
|
LAB_18013e59b:
|
|
FUN_180135ff0(iVar8,param_2);
|
|
}
|
|
}
|
|
else if (iVar8 == 0x2e6) {
|
|
uVar9 = FUN_1801c79d0(param_2);
|
|
local_84 = FUN_1800d7b30(uVar9);
|
|
}
|
|
else if (iVar8 == 0x2f4) {
|
|
uVar9 = FUN_1801c79d0(param_2);
|
|
local_39 = FUN_1800d7b50(uVar9);
|
|
}
|
|
else if (iVar8 == 0x331) {
|
|
local_c0 = FUN_1801c79d0(param_2);
|
|
}
|
|
else if (iVar8 == 0x335) {
|
|
uVar9 = FUN_1801c7aa0(param_2);
|
|
local_70 = FUN_180166bd0(uVar9);
|
|
}
|
|
else {
|
|
if (iVar8 != 0x380) goto LAB_18013e59b;
|
|
cVar6 = FUN_1801c7620(param_2);
|
|
local_3c = cVar6 != '\0';
|
|
}
|
|
}
|
|
iVar7 = FUN_1801c7f10(param_2);
|
|
}
|
|
if (local_70 == 4) {
|
|
local_3b = local_40 != 0;
|
|
}
|
|
else {
|
|
local_3b = (local_40 - 1U & 0xfffffffd) == 0;
|
|
}
|
|
local_3a = local_40 - 2U < 2;
|
|
local_d0 = 1;
|
|
FUN_180007f60(local_f0,param_3,1);
|
|
plVar10 = (longlong *)FUN_18011a830();
|
|
if (local_48 == (longlong *)0x0) {
|
|
local_110 = 0;
|
|
local_118 = &PTR_LAB_180214de8;
|
|
local_108 = 0;
|
|
(**(code **)(*plVar10 + 0xa00))(plVar10,&local_118,local_c0);
|
|
if (local_108 == 0) {
|
|
uVar11 = 1;
|
|
goto LAB_18013e795;
|
|
}
|
|
if ((local_58 != (undefined1 *)(local_108 + 0xa0)) &&
|
|
(plVar1 = *(longlong **)(local_108 + 0xb0), local_48 != plVar1)) {
|
|
if (local_48 != (longlong *)0x0) {
|
|
puVar2 = (undefined1 *)*local_48;
|
|
puVar3 = *(undefined1 **)(puVar2 + 8);
|
|
if (local_58 == puVar2) {
|
|
*local_48 = (longlong)puVar3;
|
|
}
|
|
else {
|
|
for (; puVar3 != (undefined1 *)0x0; puVar3 = *(undefined1 **)(puVar3 + 8)) {
|
|
if (puVar3 == local_58) {
|
|
*(undefined8 *)(puVar2 + 8) = *(undefined8 *)(puVar3 + 8);
|
|
break;
|
|
}
|
|
puVar2 = puVar3;
|
|
}
|
|
}
|
|
}
|
|
local_48 = plVar1;
|
|
if (plVar1 != (longlong *)0x0) {
|
|
local_50 = *plVar1;
|
|
*plVar1 = (longlong)local_58;
|
|
}
|
|
}
|
|
local_118 = &PTR_LAB_180214de8;
|
|
if (local_108 != 0) {
|
|
pppuVar4 = *(undefined ****)(local_108 + 0x30);
|
|
pppuVar5 = (undefined ***)pppuVar4[1];
|
|
if (&local_118 == pppuVar4) {
|
|
*(undefined ****)(local_108 + 0x30) = pppuVar5;
|
|
}
|
|
else {
|
|
for (; pppuVar5 != (undefined ***)0x0; pppuVar5 = (undefined ***)pppuVar5[1]) {
|
|
if (pppuVar5 == &local_118) {
|
|
pppuVar4[1] = pppuVar5[1];
|
|
break;
|
|
}
|
|
pppuVar4 = pppuVar5;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
(**(code **)(*plVar10 + 0x9f8))(plVar10,param_1,&local_f8);
|
|
uVar11 = 10;
|
|
LAB_18013e795:
|
|
FUN_18000a3c0(local_58);
|
|
local_f8 = &PTR_FUN_18021b520;
|
|
while (local_c8 != (longlong *)0x0) {
|
|
plVar10 = (longlong *)local_c8[1];
|
|
(**(code **)(*local_c8 + 8))();
|
|
local_c8 = plVar10;
|
|
}
|
|
return uVar11;
|
|
}
|
|
|
|
|
|
==============================================================================
|
|
== Flash publisher 0x1801bf030 — full decompilation
|
|
==============================================================================
|
|
|
|
void FUN_1801bf030(longlong *param_1,longlong param_2,undefined8 param_3,undefined8 param_4)
|
|
|
|
{
|
|
longlong lVar1;
|
|
longlong *plVar2;
|
|
longlong lVar3;
|
|
int iVar4;
|
|
undefined4 local_res8 [2];
|
|
undefined4 local_res10 [2];
|
|
undefined4 local_res18 [2];
|
|
undefined4 local_res20 [2];
|
|
undefined1 *local_b0;
|
|
undefined1 *local_a8;
|
|
undefined1 *local_a0;
|
|
longlong *local_98;
|
|
undefined4 local_90;
|
|
char *local_88;
|
|
longlong local_80 [2];
|
|
longlong local_70;
|
|
longlong *local_68;
|
|
|
|
(**(code **)(*param_1 + 8))
|
|
(param_1,(*(longlong *)(param_2 + 0x38) - *(longlong *)(param_2 + 0x30)) / 0x18,*param_1
|
|
,param_4,0xfffffffffffffffe);
|
|
iVar4 = 0;
|
|
lVar3 = *(longlong *)(param_2 + 0x30);
|
|
if (lVar3 != *(longlong *)(param_2 + 0x38)) {
|
|
do {
|
|
lVar1 = *(longlong *)(lVar3 + 0x10);
|
|
FUN_1800d8fa0(*(undefined8 *)(lVar1 + 0x38),local_res10,local_res8);
|
|
(**(code **)(*param_1 + 0x20))(param_1,iVar4,"TRADEID_LOWER",local_res8[0]);
|
|
(**(code **)(*param_1 + 0x20))(param_1,iVar4,"TRADEID_UPPER",local_res10[0]);
|
|
FUN_1801a9200(local_80,*(undefined4 *)(lVar1 + 0x6c));
|
|
local_98 = (longlong *)FUN_1800d7370();
|
|
local_90 = 1;
|
|
local_88 = "FUT String";
|
|
local_b0 = &DAT_1802e13a0;
|
|
local_a8 = &DAT_1802e13a0;
|
|
local_a0 = &DAT_1802e13a1;
|
|
if (*(longlong *)(lVar1 + 0x90) - 1U < 0x20f5800) {
|
|
FUN_1801c2e50(&local_b0);
|
|
}
|
|
else {
|
|
plVar2 = (longlong *)FUN_18019e320();
|
|
(**(code **)(*plVar2 + 400))(plVar2,&local_b0,"FUT_AUCTION_EXPIRED",1);
|
|
}
|
|
(**(code **)(*param_1 + 0x30))(param_1,iVar4,"DURATION",local_b0);
|
|
(**(code **)(*param_1 + 0x20))(param_1,iVar4,"TIME_REMAINING",*(undefined4 *)(lVar1 + 0x90));
|
|
(**(code **)(*param_1 + 0x20))(param_1,iVar4,"MIN_CREDITS",*(undefined4 *)(lVar1 + 0x78));
|
|
(**(code **)(*param_1 + 0x20))(param_1,iVar4,"MAX_CREDITS",*(undefined4 *)(lVar1 + 0x70));
|
|
(**(code **)(*param_1 + 0x20))(param_1,iVar4,"RESERVEDPRICE",*(undefined4 *)(lVar1 + 0x74));
|
|
(**(code **)(*param_1 + 0x20))(param_1,iVar4,"YOURBID",*(undefined4 *)(lVar1 + 0xb8));
|
|
(**(code **)(*param_1 + 0x20))(param_1,iVar4,"STATE",*(undefined4 *)(lVar1 + 0x88));
|
|
(**(code **)(*param_1 + 0x20))(param_1,iVar4,"COINS_AWARDED",*(undefined1 *)(lVar1 + 0xbf));
|
|
FUN_1800d8fa0(*(undefined8 *)(*(longlong *)(lVar1 + 0xb0) + 8),local_res18,local_res20);
|
|
(**(code **)(*param_1 + 0x20))(param_1,iVar4,"UUID_UPPER",local_res18[0]);
|
|
(**(code **)(*param_1 + 0x20))(param_1,iVar4,"UUID_LOWER",local_res20[0]);
|
|
(**(code **)(*param_1 + 0x20))
|
|
(param_1,iVar4,"CARD_ID",*(undefined4 *)(*(longlong *)(lVar1 + 0xb0) + 0x18));
|
|
(**(code **)(*param_1 + 0x20))
|
|
(param_1,iVar4,"FIFA_ID",*(uint *)(*(longlong *)(lVar1 + 0xb0) + 0x18) & 0xffffff);
|
|
(**(code **)(*param_1 + 0x20))
|
|
(param_1,iVar4,"CARD_TYPE",*(undefined4 *)(*(longlong *)(lVar1 + 0xb0) + 0x4c));
|
|
(**(code **)(*param_1 + 0x20))
|
|
(param_1,iVar4,"CARD_OFFERSTATE",*(undefined4 *)(*(longlong *)(lVar1 + 0xb0) + 0x5c)
|
|
);
|
|
(**(code **)(*param_1 + 0x20))(param_1,iVar4,"IS_WATCHED",*(undefined1 *)(lVar1 + 0xbc));
|
|
(**(code **)(*param_1 + 0x20))(param_1,iVar4,"INBOX",*(undefined1 *)(lVar1 + 0xbe));
|
|
(**(code **)(*param_1 + 0x20))(param_1,iVar4,"IS_GLOW",*(undefined1 *)(lVar1 + 0xbd));
|
|
(**(code **)(*param_1 + 0x18))(param_1,iVar4,"TRADE_DATA_AVAILABLE",1);
|
|
if (1 < (longlong)local_a0 - (longlong)local_b0) {
|
|
if (local_b0 != (undefined1 *)0x0) {
|
|
(**(code **)(*local_98 + 0x18))(local_98,local_b0,(int)local_a0 - (int)local_b0);
|
|
}
|
|
}
|
|
if ((1 < local_70 - local_80[0]) && (local_80[0] != 0)) {
|
|
(**(code **)(*local_68 + 0x18))(local_68,local_80[0],(int)local_70 - (int)local_80[0]);
|
|
}
|
|
lVar3 = lVar3 + 0x18;
|
|
iVar4 = iVar4 + 1;
|
|
} while (lVar3 != *(longlong *)(param_2 + 0x38));
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
==============================================================================
|
|
== strings: sold / clear / inbox / glow / collect
|
|
==============================================================================
|
|
sold 0x180228bed 'sold'
|
|
sold 0x18022f524 'sold'
|
|
Sold 0x1801efaf1 'SoldFromTradePile'
|
|
Sold 0x1802302cf 'SoldBid'
|
|
Sold 0x1802302df 'SoldBuyNow'
|
|
SOLD 0x18020a0c7 'SOLD'
|
|
clearSold ABSENT
|
|
ClearSold ABSENT
|
|
INBOX 0x180215044 'INBOX'
|
|
inbox ABSENT
|
|
IS_GLOW 0x1802151a0 'IS_GLOW'
|
|
glow ABSENT
|
|
Glow ABSENT
|
|
collect 0x1802307e0 'collector'
|
|
Collect 0x1801ec3c1 'CollectedCards'
|
|
Collect 0x1801ec3f8 'Collection'
|
|
Collect 0x1801ec422 'Collection'
|
|
Collect 0x1801ec449 'Collection'
|
|
unclaimed 0x18022fd68 'unclaimedPrizesChampionEvents'
|
|
claim 0x1802099d1 'claimedPack'
|
|
claim 0x1802099e9 'claimedPack2'
|
|
claim 0x18022fd6a 'claimedPrizesChampionEvents'
|