Root cause

The Vulnerable Contract has a function that receives tokens via transferFrom and sends STRAC tokens. However, due to improper validation of the received token, it ultimately fails to receive any tokens and ends up sending STRAC tokens instead.

Vulnerable code snippet

The victim contract is not verified on Bscscan. The decompiled result of the vulnerable function is as follows:

function 0x4a75084c(address varg0, address varg1, uint256 varg2) public nonPayable {  find similar
    require(msg.data.length - 4 >= 96);
@>  if (!(varg0 - owner_3_0_19)) {
        v0, /* bool */ v1 = owner_3_0_19.isWhitelist(msg.sender).gas(msg.gas);
        require(bool(v0), 0, RETURNDATASIZE()); // checks call status, propagates error data on error
        require(MEM[64] + RETURNDATASIZE() - MEM[64] >= 32);
        require(v1 == bool(v1));
        require(0 - bool(v1), Error('swapss fail.'));
    }
    v2, /* bool */ v3 = varg0.transferFrom(msg.sender, this, varg2).gas(msg.gas);
    require(bool(v2), 0, RETURNDATASIZE()); // checks call status, propagates error data on error
    require(MEM[64] + RETURNDATASIZE() - MEM[64] >= 32);
    require(v3 == bool(v3));
    v4, /* bool */ v5 = varg1.transfer(msg.sender, varg2).gas(msg.gas);
    require(bool(v4), 0, RETURNDATASIZE()); // checks call status, propagates error data on error
    require(MEM[64] + RETURNDATASIZE() - MEM[64] >= 32);
    require(v5 == bool(v5));
}

It appears to be validating the token address using the trusted address, owner_3_0_19, which is the STRAC Token Contract address. However, upon analyzing the code, it becomes clear that if the provided token address is different from the trusted owner_3_0_19, no validation is performed, and the function proceeds without any checks.

image.png

Attack tx

https://app.blocksec.com/explorer/tx/bsc/0x1147b3c0f3ebdd524c4e58430bb736eba9f7fa522158f5ad81eb3e2394b466d0

Analysis

https://x.com/DecurityHQ/status/1673769624611987487

image.png