DeFiFoundrySolidity
16,653 OP
View results
Submission Details
Severity: high
Invalid

Exchange function in Transmuter allows balance manipulation and unlimited token minting

Summary

The exchange() function in the Transmuter contract allows users to exchange more tokens than the total available (totalUnexchanged), leading to potential unlimited minting of tokens and balance manipulation.

Vulnerability Details

In ITransmuter.sol, the exchange() function lacks proper balance checks:

function exchange(uint256 _amount) external;
function totalUnexchanged() external view returns (uint256);
function totalBuffered() external view returns (uint256);

PoC:

function testExchangeBalanceManipulation() public {
uint256 amount = 100e18;
vm.startPrank(attacker);
// Mock initial balances
vm.mockCall(
address(transmuter),
abi.encodeWithSelector(ITransmuter.totalUnexchanged.selector),
abi.encode(amount)
);
vm.mockCall(
address(transmuter),
abi.encodeWithSelector(ITransmuter.totalBuffered.selector),
abi.encode(amount * 2)
);
// Attacker exchanges more than totalUnexchanged
transmuter.exchange(amount * 2); // This succeeds when it shouldn't
// Verify exchange succeeded
assertEq(
transmuter.getExchangedBalance(attacker),
amount * 2,
"Exchange manipulation succeeded"
);
}

Impact

  • Unlimited token minting possible

  • Balance manipulation

  • Economic damage to the protocol

  • Potential drain of underlying assets

  • Hyperinflation of synthetic tokens

Tools Used

  • Foundry

  • Manual Review

Recommendations

  1. Add balance checks in exchange function:

function exchange(uint256 _amount) external {
require(_amount <= totalUnexchanged(), "Amount exceeds total unexchanged");
require(_amount <= getUnexchangedBalance(msg.sender), "Insufficient balance");
// ... rest of the function
}
  1. Implement exchange limits:

uint256 public constant MAX_EXCHANGE_RATIO = 50; // 50%
function exchange(uint256 _amount) external {
require(_amount <= totalUnexchanged() * MAX_EXCHANGE_RATIO / 100, "Exchange limit exceeded");
// ... rest of the function
}
  1. Add emergency pause mechanism:

bool public exchangePaused;
modifier whenExchangeNotPaused() {
require(!exchangePaused, "Exchange paused");
_;
}
function exchange(uint256 _amount) external whenExchangeNotPaused {
// ... function implementation
}
Updates

Appeal created

inallhonesty Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

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