Platform: Code4rena
Start Date: 09/12/2022
Pot Size: $90,500 USDC
Total HM: 35
Participants: 84
Period: 7 days
Judge: GalloDaSballo
Total Solo HM: 12
Id: 192
League: ETH
Rank: 62/84
Findings: 2
Award: $61.52
π Selected for report: 0
π Solo Findings: 0
π Selected for report: 0x4non
Also found by: 0xNazgul, Deivitto, __141345__, cccz, eierina, imare, kwhuo68, rvierdiiev
60.3691 USDC - $60.37
Inside the Lock
contract claimGovFees
function can be DOSed on tokens like USDT, KNC because token like this needs to first be approved to zero.
In case claimGovFees
reverts because a token like this. The Lock
contract functionality is compromised because claimGovFees
is internally the first call in all the main contract methods:
release
claim
claimDebt
lock
Notice:
The problem is that a token like this cannot be whitelisted with Lock::editAsset
because it comes from bondNFT
state variable. And this BondNFT
contract can add an unsupported token later with BondNFT::addAsset
. And once is added it cannot be removed. Even setAllowedAsset
will not stop the DOSing because BondNFT::getAssets()
will still return the offending token.
Manual review
Approve ERC20 token to zero first.
function claimGovFees() public { address[] memory assets = bondNFT.getAssets(); for (uint i=0; i < assets.length; i++) { uint balanceBefore = IERC20(assets[i]).balanceOf(address(this)); IGovNFT(govNFT).claim(assets[i]); uint balanceAfter = IERC20(assets[i]).balanceOf(address(this)); + IERC20(assets[i]).approve(address(bondNFT), 0); IERC20(assets[i]).approve(address(bondNFT), type(uint256).max); bondNFT.distribute(assets[i], balanceAfter - balanceBefore); } }
#0 - c4-judge
2022-12-20T15:49:37Z
GalloDaSballo marked the issue as duplicate of #104
#1 - c4-judge
2023-01-22T17:45:47Z
GalloDaSballo marked the issue as satisfactory
π Selected for report: 0xA5DF
Also found by: 0xA5DF, 0xNazgul, 0xSmartContract, 0xbepresent, 0xdeadbeef0x, 8olidity, Englave, Faith, HE1M, JohnnyTime, Madalad, Mukund, Ruhum, SmartSek, __141345__, aviggiano, carlitox477, cccz, chaduke, francoHacker, gz627, gzeon, hansfriese, hihen, imare, jadezti, kwhuo68, ladboy233, orion, peanuts, philogy, rbserver, wait, yjrwkk
1.1472 USDC - $1.15
https://github.com/code-423n4/2022-12-tigris/blob/588c84b7bb354d20cbca6034544c4faa46e6a80e/contracts/GovNFT.sol#L64-L71 https://github.com/code-423n4/2022-12-tigris/blob/588c84b7bb354d20cbca6034544c4faa46e6a80e/contracts/GovNFTBridged.sol#L48-L55
The method _bridgeMint
is used inside NFT token contracts in two cases:
When new tokens are to be minted by receiving the message from layerZero. In this case _bridgeMint
is called inside _nonblockingLzReceive
internal function
If a transaction from layerZero fails it can be replayed with the method retryMessage
which again calls _nonblockingLzReceive
which calls _bridgeMint
As we can see its used to create new tokens from other chains in a first attempt or a latter retry. And because of this it can be only called by the owner (for replaying failed messages) or by the bridge address (when receiving a message).
require(msg.sender == address(this) || _msgSender() == owner(), "NotBridge");
The main problem is that it can be also called at will by the contract owner because it is a public contract method. And the only check for minting new token is that we pass a tokenId that is smaller then the maximal tokens cap.
It should never happen but by the current contract implementation it can happen. (example by a leakage of the owner private key etc.)
Manual review
Change _bridgeMint
access from public to internal. It will still work for replaying and receiving new messages. But it can not be called at will.
#0 - c4-judge
2022-12-23T17:45:25Z
GalloDaSballo marked the issue as primary issue
#1 - TriHaz
2022-12-26T11:37:21Z
We are aware of the centralization risks, owner will be a multi-sig treasury for now. I think this should be low risk.
#2 - c4-sponsor
2022-12-26T11:37:29Z
TriHaz marked the issue as sponsor acknowledged
#3 - c4-sponsor
2022-12-26T11:37:58Z
TriHaz marked the issue as disagree with severity
#4 - GalloDaSballo
2023-01-16T08:14:49Z
Making dup of #377 as it highlights a centralization risk
#5 - c4-judge
2023-01-16T08:15:23Z
GalloDaSballo marked the issue as duplicate of #377
#6 - c4-judge
2023-01-22T17:34:50Z
GalloDaSballo marked the issue as satisfactory