Dai++
Description¶
MakerDAO is such a complex codebase, and we all know that larger codebases are more likely to have bugs. I simplified everything, so there shouldn't be any bugs here.
Deploy.s.sol
src/Challenge.sol
src/SystemConfiguration.sol
src/Account.sol
AccountManager.sol
src/Stablecoin.sol
Solution¶
- The challenge is solved if the total supply of
Stablecoin
is greater than \(10^{12} \times 10^{18}\) - Accounts authorized by the
SystemConfiguration
contract can mint stable coins. Only the owner ofSystemConfiguration
can update system contracts (i.e. authorized accounts) and theAccountManager
contract is the only authorized contract -
In the
AccountManager
contract, only valid accounts can mint stable coins. Meanwhile, the debt on the account will increase -
In the
increaseDebt()
function, if the account is not healthy after the debt is increased, the transaction will fail. However, the player don't have enough ETH to mint \(10^{12}\) stable coins and keep the account healthy -
Notice that
AccountManager
usesClonesWithImmutableArgs
to create new accounts. When interacting with theAccount
, the immutable arguments will be read from calldata, saving gas costs. However, there's a comment in theClonesWithImmutableArgs
-
Since the immutable arguments are stored in the code region of the created proxy contract, the code size will be calculated based on the data length during the deployment. However, the code size that should be returned is also stored in 2 bytes. Therefore, if
runSize
exceeds 65535 bytes, a broken contract may be deployed. We can then treatincreaseDebt()
as a phantom function and ignore the call -
The existing arguments length is
20 + 20 + 32 = 72
bytes and the length of encodedrecoveryAddresses
will be a multiple of 32 bytes
Exploitation¶
Flag¶
PCTF{0V3RFl0W5_WH3r3_Y0u_L3a57_3xp3C7_17}