I asked claude to check for obvious security vulnerabilitie BTW. Here is what it found that may or may not be on your radar, I will paste as I asked claude to format it, let me know if relevant or not:
Bug A — Free Gas Exploit: Any User Can Steal Gas Reserve (Critical)
File: account-mapping/evm-mapping-contract/contract/main.go:81
File: account-mapping/evm-mapping-contract/contract/mapping/types.go:24
File: account-mapping/evm-mapping-contract/contract/mapping/handlers.go:147-149
What it is
The EVM bridge has a shared "gas reserve" — ETH held by the contract to pay Ethereum gas fees when
processing withdrawals. Users are supposed to pay this fee themselves on top of their withdrawal.
There is a boolean field deduct_fee in the withdrawal request that is supposed to mark whether the
fee should be deducted from the amount (e.g., a relayer covering fees on behalf of a user). The
problem: there is no access control on this field. Any user can set it to true in their JSON.
The code
// main.go:81 — no access control, input parsed directly from user JSON
func unmapETH(input *string) *string {
var params mapping.TransferParams
json.Unmarshal([]byte(*input), ¶ms) // DeductFee comes straight from user
...
}
// types.go:24
DeductFee bool `json:"deduct_fee"` // user controls this
// handlers.go:147-149 — when true, fee is simply... dropped
totalDeduct := amount + fee
if params.DeductFee {
totalDeduct = amount // fee not charged to anyone
}
The calculated fee (Ethereum gas cost) is never charged to the gas reserve, never deducted from
the caller — it just disappears. The contract still pays real Ethereum gas from the reserve. Every
withdrawal with deduct_fee: true drains the gas reserve slightly without anyone paying for it.
How to exploit
Send a withdrawal with:
{ "amount": "10000000000000000", "to": "0xYourAddress", "deduct_fee": true }
Repeat until the gas reserve drops below MinGasReserve (0.05 ETH), at which point all
withdrawals for all users are permanently blocked until an admin manually refills the reserve.
Bug B — Funds Permanently Trapped: int64 Balance Ceiling (High)
File: account-mapping/evm-mapping-contract/contract/mapping/balance.go:46-53
File: account-mapping/evm-mapping-contract/contract/mapping/handlers.go (all deposit handlers)
What it is
All balances in the EVM bridge are stored as Go int64 (a signed 64-bit integer). The maximum
value of int64 is 9,223,372,036,854,775,807 — which in wei equals approximately 9.22 ETH.
If a user's balance is near this ceiling and they deposit more ETH, the IncBalance function
correctly detects an overflow and returns an error. But here is the problem: the ETH is already
sitting in the Ethereum vault at the moment this error is returned. The Ethereum transaction
confirming the deposit has already been included in a block and verified via Merkle proof.
The code
// balance.go:46
func IncBalance(address, asset string, amount int64) error {
bal := GetBalance(address, asset)
newBal, err := safeAdd64(bal, amount)
if err != nil {
return err // <-- deposit rejected, but ETH is already in the vault
}
SetBalance(address, asset, newBal)
return nil
}
The deposit is also marked as "observed" before IncBalance is called, so it cannot be replayed.
There is no refund path. The ETH is stuck in the Ethereum vault with no way out.
How to trigger
A user who has accumulated ~9 ETH in the bridge and then deposits 1 more ETH will lose the 1 ETH.
It arrives in the Ethereum vault, the Magi contract rejects the credit, and the funds are gone.
Since 9.22 ETH is not a huge amount for a bridge, this affects any moderately active user and
becomes more likely as the bridge grows in usage.
Bug C — Permanent Fund Loss in transferFrom (High, triggered by Bug B)
File: account-mapping/evm-mapping-contract/contract/mapping/handlers.go:460-466
What it is
The HandleTransferFrom function (the ERC-20-style "spend approved funds" operation) has its steps
in the wrong order. It removes funds from the sender before crediting the recipient. If
crediting the recipient fails, the sender's funds are gone with no rollback.
The code
// handlers.go:460-466
if !DecBalance(params.From, params.Asset, amount) { // 1. funds removed from sender ✓
return errors.New("insufficient balance")
}
SetAllowance(params.From, caller, params.Asset, allowance-amount) // 2. allowance consumed ✓
if err := IncBalance(params.To, params.Asset, amount); err != nil { // 3. credit recipient
return errors.New("recipient balance overflow") // funds are GONE — no rollback
}
When step 3 fails (which happens when the recipient's balance is near the 9.22 ETH int64 ceiling
described in Bug B), the sender has already lost their funds. The error message "recipient balance
overflow" is returned to the caller, but the state is permanently corrupted — sender balance is
reduced, recipient balance is unchanged.
Conditions for exploitation
This bug requires the recipient's balance to be near math.MaxInt64 (≈9.22 ETH equivalent in the
token's smallest unit). This is the same condition as Bug B, making the two bugs compounding:
Bug B causes ETH deposits to get trapped
Bug C causes token transfers to drain senders when Bug B conditions are present in the recipient
A malicious actor who knows about Bug B could craft a scenario where a target address is near the
ceiling, then trigger a transferFrom against them to silently burn the sender's tokens.
PS: Note from reading bug C, I used to work with Solidity and smart contracts early in my career, the logic of deducting before crediting is standard and usually the ideal, however this is go, not solidity, I think there is no equivalent of assert or requiring or just throwing the transaction invalidating and rolling back previous operations, the huge problem with fixing this is how to rollback a transaction in a way that does not create yet another possible exploit?
Well, as I said, the bugs above were AI found, they may or not be relevant, I have no context on the project and haven't worked with smart contracts in years and don't have time to evaluate them myself, but worth sharing.
But then that is why I raised the problem of AI generated code. AI can delivery so much code that it is extremely hard to review and investigate. It happens often that when we are done generating code we have so much technical debt and backlog that the work is endless. Then one fix becomes two bugs that require 2 fixes that generate 4 bugs. Be careful not to fight an Hydra with the code base. More code in general means more risk and more vectors.
You seem to have a large team from what you mention, I can only hope they are all experienced enough and beyond average enough.
RE: Magi Network DHF Proposal 2026