BGEO Mint Drain
Exploit Transactions
0x9f4ef3cc55b016ea6b867807a09f80d1b2e36f6cd6fccfaf0182f46060332c57Victim Addresses
0xc342774492b54ce5f8ac662113ed702fc1b34972BSC0x88503f48e437a377f1ac2892cbb3a5b09949faddBSCLoss Breakdown
Similar Incidents
Public Mint Drains USDT Pair
40%PHIL Public Mint Drain
38%APIG Self-Transfer Mint Drain
35%LAYER3 Oracle-Mint Drain
35%BSC PoolWithdraw Signature-Bypass Drains USDT Pool
34%BOBO Dual-Market Drain
33%Root Cause Analysis
BGEO Mint Drain
1. Incident Overview TL;DR
On BSC transaction 0x9f4ef3cc55b016ea6b867807a09f80d1b2e36f6cd6fccfaf0182f46060332c57 at block 22315680, the attacker EOA 0xde01f6ce91e4f4bdb94bb934d30647d72182320f called helper contract 0x08a525104ea2a92abbce8e4e61c667eed56f3b42, which minted counterfeit BGEO directly into the BGEO/WBNB PancakePair 0x88503f48e437a377f1ac2892cbb3a5b09949fadd and immediately swapped it for WBNB. The exploit extracted 12030000000000000000 wei of WBNB, with 2232630000000000 wei paid in gas, for a positive post-fee outcome.
The root cause is in BGeoToken 0xc342774492b54ce5f8ac662113ed702fc1b34972: the mint authorization path accepts empty signature arrays. Because the contract only checks that _r, _s, and _v have equal length, and because its signer-validation loop returns true on an empty array, any unprivileged caller can mint arbitrary BGEO.
2. Key Background
BGEO is intended to be a signer-gated mintable token. Its mint(uint256,string,address,bytes32[],bytes32[],uint8[]) path hashes (chain id, msg.sender, tx hash, amount) and is supposed to verify that the recovered signers belong to the configured signer set.
The drained venue is a PancakeSwap V2 pair holding WBNB against BGEO. Pancake V2 pairs trust token balances and reserve accounting. If a listed token can be forged without cost, the pair interprets the forged balance increase as swap input and releases the paired real asset.
3. Vulnerability Analysis & Root Cause Summary
The vulnerability class is an authorization bypass in a signer-gated mint function. In the verified BGEO source, checkSignParams returns true whenever _r, _s, and _v have matching lengths, including the all-zero-length case. The isSigned modifier then allocates an address array of length _r.length; when _r.length == 0, the recovery loop executes zero times. The next check calls isSigners, which iterates over the supplied signer array and returns true when the array is empty. As a result, mint proceeds to _mint(_receiver, _amount) without validating any signer approval. The broken invariant is clear: minting should require at least one valid configured signer for the exact (caller, tx hash, amount) tuple. Instead, the implementation treats an empty witness set as authorized.
Relevant victim code:
modifier isSigned(
string memory _txHash,
uint256 _amount,
bytes32[] memory _r,
bytes32[] memory _s,
uint8[] memory _v
) {
require(checkSignParams(_r, _s, _v), "bad-sign-params");
bytes32 _hash = keccak256(abi.encodePacked(bsc, msg.sender, _txHash, _amount));
address[] memory _signers = new address[](_r.length);
for (uint8 i = 0; i < _r.length; i++) {
_signers[i] = ecrecover(_hash, _v[i], _r[i], _s[i]);
}
require(isSigners(_signers), "bad-signers");
_;
}
function isSigners(address[] memory _signers) public view returns (bool){
for (uint8 i = 0; i < _signers.length; i++) {
if (!_containsSigner(_signers[i])) {
return false;
}
}
return true;
}
Snippet origin: verified BGeoToken source.
4. Detailed Root Cause Analysis
The exploitable pre-state existed immediately before block 22315680. The pair already held live WBNB liquidity, and BGEO mint authorization depended entirely on the flawed isSigned modifier. An attacker did not need any privileged signer key, private calldata, or prior ownership.
The exploit transaction was sent by EOA 0xde01f6ce91e4f4bdb94bb934d30647d72182320f to helper contract 0x08a525104ea2a92abbce8e4e61c667eed56f3b42. The trace shows the helper contract invoking:
BGeoToken::mint(1000000000000000000000000000000 [1e30], "t", PancakePair: [0x88503F48e437a377f1aC2892cBB3a5b09949faDd], [], [], [])
That call succeeded and emitted a mint transfer of 1e30 BGEO into the pair:
emit Transfer(from: 0x0000000000000000000000000000000000000000,
to: PancakePair: [0x88503F48e437a377f1aC2892cBB3a5b09949faDd],
value: 1000000000000000000000000000000 [1e30])
Snippet origin: seed transaction trace.
The balance-diff artifact independently confirms the pair's BGEO balance delta was exactly 1000000000000000000000000000000. Once the forged BGEO sat in the pair, the helper contract called PancakePair swap, causing the pair to transfer WBNB to the attacker EOA:
PancakePair::swap(12030000000000000000 [1.203e19], 0, 0xde01f6Ce91E4F4bdB94BB934d30647d72182320F, 0x)
WBNB::transfer(0xde01f6Ce91E4F4bdB94BB934d30647d72182320F, 12030000000000000000 [1.203e19])
Snippet origin: seed transaction trace.
This is the full breakpoint chain: empty signature arrays satisfy checkSignParams, produce an empty recovered-signer array, pass isSigners, allow _mint, inject counterfeit BGEO into the AMM, and let the attacker convert that counterfeit inventory into real WBNB liquidity.
5. Adversary Flow Analysis
The adversary execution was a single attacker-crafted transaction.
- The attacker EOA
0xde01f6ce91e4f4bdb94bb934d30647d72182320fsubmitted transaction0x9f4ef3cc55b016ea6b867807a09f80d1b2e36f6cd6fccfaf0182f46060332c57targeting helper contract0x08a525104ea2a92abbce8e4e61c667eed56f3b42. - The helper contract called BGEO
mintwith amount1e30, alias"t", receiver equal to the PancakePair, and all three signature arrays empty. - BGEO accepted the empty witness set and minted
1e30BGEO directly to the pair. - The helper contract then called
swapon pair0x88503f48e437a377f1ac2892cbb3a5b09949fadd, routing WBNB proceeds to the attacker EOA. - The trace shows the pair released
12.03WBNB to the attacker, and the balance diff shows only0.00223263BNB spent on gas.
The relevant adversary-controlled accounts are the EOA 0xde01f6ce91e4f4bdb94bb934d30647d72182320f and helper contract 0x08a525104ea2a92abbce8e4e61c667eed56f3b42. Their roles are directly evidenced by sender, target, swap caller, and profit-recipient positions in the trace.
6. Impact & Losses
The direct economic loss was borne by the BGEO/WBNB PancakePair, which released real WBNB against counterfeit BGEO inventory. The measured asset loss is:
- WBNB:
12030000000000000000raw units (12.03WBNB), decimal18
The attacker's net economic result remained positive after subtracting 2232630000000000 wei of native gas cost from the traced WBNB payout.
7. References
- Seed transaction:
0x9f4ef3cc55b016ea6b867807a09f80d1b2e36f6cd6fccfaf0182f46060332c57 - Attacker EOA:
0xde01f6ce91e4f4bdb94bb934d30647d72182320f - Attacker helper contract:
0x08a525104ea2a92abbce8e4e61c667eed56f3b42 - Victim token: BGeoToken
0xc342774492b54ce5f8ac662113ed702fc1b34972 - Drained venue: PancakePair
0x88503f48e437a377f1ac2892cbb3a5b09949fadd - Verified victim source showing the bypass: BGeoToken
isSigned,isSigners,checkSignParams, andmint - On-chain execution evidence: seed transaction trace and balance-diff artifacts for the same transaction