Platform: Code4rena
Start Date: 18/10/2023
Pot Size: $36,500 USDC
Total HM: 17
Participants: 77
Period: 7 days
Judge: MiloTruck
Total Solo HM: 5
Id: 297
League: ETH
Rank: 75/77
Findings: 1
Award: $8.30
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: MrPotatoMagic
Also found by: 0xMosh, 0xPsuedoPandit, 0xhacksmithh, 8olidity, Al-Qa-qa, Baki, Bughunter101, Krace, Stormreckson, T1MOH, Tendency, eeshenggoh, fibonacci, hals, immeas, kutugu, lsaudit, m4k2, mrudenko, okolicodes, phoenixV110, spark, twicek, xAriextz
8.3007 USDC - $8.30
Not being able to be the SafeManager and NFTRenderer of the vault, allowing malicious actors to take over the vault and break the protocol.
P.S I consider this as high risk because this exploit is a multiple of DOS, Frontrunning and Access Control which can lead to protocol failure.
It should be avoided that the implementation of contracts can be initialized by third parties. This can be the case if the initializeManager
& initializeRenderer
function is unprotected. Since the implementation contract is not meant to be used directly without the SafeManager it is recommended to protect the initialization method of the implementation using access control.
The pragmatic way of exploiting such case is by frontrunning:
initializeManager
or initializeRenderer
initializeManager
or initializeRenderer
You will notice that the initializeManager & initializeManager functions do check if the function has been called. Since we know that the default value of the address variable is zero-state this means that once we called the function, it can only be called once.
contracts/proxies/ODSafeManager.sol constructor(address _safeEngine, address _vault721) { safeEngine = _safeEngine.assertNonNull(); vault721 = IVault721(_vault721); vault721.initializeManager(); } https://github.com/open-dollar/od-contracts/blob/f4f0246bb26277249c1d5afe6201d4d9096e52e6/src/contracts/proxies/ODSafeManager.sol#L64C1-L68C4
contracts/proxies/NFTRenderer.sol constructor(address _vault721, address oracleRelayer, address taxCollector, address collateralJoinFactory) { vault721 = IVault721(_vault721); vault721.initializeRenderer(); _safeManager = IODSafeManager(vault721.safeManager()); _safeEngine = ISAFEEngine(_safeManager.safeEngine()); _oracleRelayer = IOracleRelayer(oracleRelayer); _taxCollector = ITaxCollector(taxCollector); _collateralJoinFactory = ICollateralJoinFactory(collateralJoinFactory); } https://github.com/open-dollar/od-contracts/blob/f4f0246bb26277249c1d5afe6201d4d9096e52e6/src/contracts/proxies/NFTRenderer.sol#L35C1-L43C4
contracts/proxies/Vault721.sol function initializeManager() external { if (address(safeManager) == address(0)) _setSafeManager(msg.sender); } function initializeRenderer() external { if (address(nftRenderer) == address(0)) _setNftRenderer(msg.sender); } https://github.com/open-dollar/od-contracts/blob/f4f0246bb26277249c1d5afe6201d4d9096e52e6/src/contracts/proxies/Vault721.sol#L56C1-L58C4
Manual Review
Protect initialization methods from being called by unauthorized parties. Create RBAC only allowing Vault and NFTRenderer contracts to only access the specified functions.
Access Control
#0 - c4-pre-sort
2023-10-26T01:04:02Z
raymondfam marked the issue as low quality report
#1 - c4-pre-sort
2023-10-26T01:04:29Z
raymondfam marked the issue as duplicate of #16
#2 - c4-judge
2023-11-01T20:00:25Z
MiloTruck changed the severity to QA (Quality Assurance)
#3 - c4-judge
2023-11-03T18:04:51Z
MiloTruck marked the issue as grade-b