Dria

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

Improper Handling of Unregistration and Token Transfer

Summary

In the LLMOracleRegistry contract, the unregister function is designed to remove an oracle's registration and return the staked tokens to the oracle. However, instead of transferring the staked tokens directly back to the user, the function erroneously calls:

token.approve(msg.sender, token.allowance(address(this), msg.sender) + amount);

This line increases the ERC20 token allowance for the user (msg.sender) to spend tokens from the registry's balance. Specifically, it adds the staked amount to the existing allowance rather than transferring the tokens outright. Consequently, users are granted the ability to transfer tokens from the registry contract using transferFrom, but the tokens remain in the registry unless the user actively initiates the transfer.

Vulnerability Details

  • The oracle calls the unregister function, which deletes their registration and emits the Unregistered event.

  • Instead of transferring the staked tokens back, the function increases the allowance for the oracle to spend tokens from the registry by calling token.approve(msg.sender, token.allowance(address(this), msg.sender) + amount).

  • The oracle, having an increased allowance, can now call transferFrom to move the approved amount of tokens from the registry to their own address.

  • Alternatively, if the oracle is compromised, an attacker could use the allowance to drain tokens from the registry without the oracle's consent.

Impact

The vulnerability primarily relies on the oracle being compromised or acting maliciously. Since oracles are assumed to be trusted entities within the protocol, the likelihood of such exploitation is minimal.

Tools Used

Manual Review

Recommendations

Modify the unregister function to transfer the staked tokens directly back to the user instead of adjusting allowances.

function unregister(LLMOracleKind kind) public returns (uint256 amount) {
amount = registrations[msg.sender][kind];
// Ensure the user is registered
if (amount == 0) {
revert NotRegistered(msg.sender);
}
// Unregister the user
delete registrations[msg.sender][kind];
emit Unregistered(msg.sender, kind);
- // approve its stake back
- token.approve(msg.sender, token.allowance(address(this), msg.sender) + amount);
+ // Transfer tokens back to the user
+ bool success = token.transfer(msg.sender, amount);
+ require(success, "Token transfer failed");
}
Updates

Lead Judging Commences

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

Support

FAQs

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