Belt Crosschain AMM Audit (Pt. 2)
Smart Contract Security Assessment
Dec 1, 2021

SUMMARY
ABSTRACT
Dedaub was commissioned to perform a security audit on the Belt Finance Crosschain AMM contracts. We received the code base in the form of an archive file on Nov. 1, 2021. The primary contracts (non-test, non-interface, non-mock) are listed below:
crosschain/SwapReceiver.sol
crosschain/Router.sol
crosschain/FeeStore.sol
crosschain/Escrow.sol
crosschain/exchanges/ExchangeProxy.sol
SETTING & CAVEATS
The audited code base is of small size, at nearly 1KLoC. About half of it is completely newly audited code (new contracts FeeStore.sol, Escrow.sol).
VULNERABILITIES & FUNCTIONAL ISSUES
This section details issues that affect the functionality of the contract. Dedaub generally categorizes issues according to the following severities, but may also take other considerations into account such as impact or difficulty in exploitation:
- User or system funds can be lost when third-party systems misbehave
- DoS, under specific conditions
- Part of the functionality becomes unusable due to a programming error
- Breaking important system invariants but without apparent consequences
- Buggy functionality for trusted users where a workaround exists
- Security issues which may manifest when the system evolves
Issue resolution includes “dismissed”, by the client, or “resolved”, per the auditors.
CRITICAL SEVERITY
[No critical severity issues]
HIGH SEVERITY
In SwapReceiver::onTokenBridgeReceived, value amountOut results in wrong calculation in case of AddLiquidity transaction type:
address tokenOut = request.tokenOut;
/// Dedaub: amountOut should be calculated after the next if statement
uint amountOut = _getTokenBalance(tokenOut);
if (txType == TransactionType.AddLiquidity) {
tokenOut = address(ISwap(stableSwap).lpToken());
}
/// Dedaub: requestLiquidity or requestSwap called
amountOut = _getTokenBalance(tokenOut).sub(amountOut);
This can be exploited as follows: an attacker can initiate a valid AddLiquidity transaction and provide request.tokenOut data with any token of no or really low balance for the SwapReceiver contract. This fact will pass unnoticed, since nowhere in the code is reqest.tokenOut actually checked against the LP token. Because of the initial wrong balance accounting (amountOut calculated on request.tokenOut instead of lpToken) the attacker will get the whole lpToken balance of the contract.
MEDIUM SEVERITY
[No medium severity issues]
LOW SEVERITY
[No low severity issues]
OTHER/ ADVISORY ISSUES
This section details issues that are not thought to directly affect the functionality of the project, but we recommend addressing them.
In SwapReceiver::_requestLiquidity, parameter txType is of TransactionType so the following cast is redundant:
if (TransactionType(txType) == TransactionType.AddLiquidity) {