codehawks-2023-07-dsc-m06
[M-06] Double-spending vulnerability leads to a disruption of the DSC token
Summary
생성자에서 담보 토큰을 등록할 때 이를 배열에 저장한다. 담보의 양을 조회할 때는 배열을 순회하며 확인한다. 이 때 중복으로 주소를 등록했는지 체크하지 않으므로, 실수로 생성자에 중복으로 저장한 경우 실제보다 많은 담보가 예치된 것으로 판단하게 된다.
Keyword
lack of input validation, double spending
Vulnerability
생성자에서 배열로 담보 토큰 주소들을 파라미터로 받아 배열에 저장한다.
이 때, 담보 토큰 주소 배열에 중복 값이 있는지 확인하지 않는다.
constructor(address[] memory tokenAddresses, address[] memory priceFeedAddresses, address dscAddress) {
// USD Price Feeds
if (tokenAddresses.length != priceFeedAddresses.length) {
revert DSCEngine__TokenAddressesAndPriceFeedAddressesMustBeSameLength();
}
// For example ETH / USD, BTC / USD, MKR / USD, etc
for (uint256 i = 0; i < tokenAddresses.length; i++) {
s_priceFeeds[tokenAddresses[i]] = priceFeedAddresses[i];
@> s_collateralTokens.push(tokenAddresses[i]);
}
i_dsc = DecentralizedStableCoin(dscAddress);
}이 배열을 순회하며 소유한 담보 토큰을 집계한다. 이 때 역시 동일 토큰을 중복으로 처리했는지는 확인하지 않는다.
function getAccountCollateralValue(address user) public view returns (uint256 totalCollateralValueInUsd) {
// loop through each collateral token, get the amount they have deposited, and map it to
// the price, to get the USD value
@> for (uint256 i = 0; i < s_collateralTokens.length; i++) {
@> address token = s_collateralTokens[i];
@> uint256 amount = s_collateralDeposited[user][token];
@> totalCollateralValueInUsd += getUsdValue(token, amount);
@> }
return totalCollateralValueInUsd;
}따라서 생성자에서 실수로 동일 담보 토큰을 중복으로 등록한다면 담보의 양이 실제 예치한 것보다 더 크게 잡히게 된다.
Impact
담보가 실제보다 크게 잡히면 실제로 받아야하는 DSC 토큰보다 많은 양을 받을 수 있고, 200%의 담보율이 깨져 디페깅을 야기한다.
Mitigation
동일한 담보 토큰 주소를 중복으로 등록할 수 없도록 생성자에서 막는다.
constructor(address[] memory tokenAddresses, address[] memory priceFeedAddresses, address dscAddress) {
// USD Price Feeds
if (tokenAddresses.length != priceFeedAddresses.length) {
revert DSCEngine__TokenAddressesAndPriceFeedAddressesMustBeSameLength();
}
// For example ETH / USD, BTC / USD, MKR / USD, etc
for (uint256 i = 0; i < tokenAddresses.length; i++) {
+ require(s_priceFeeds[tokenAddresses[i]] == address(0), "Collateral token was already set");
s_priceFeeds[tokenAddresses[i]] = priceFeedAddresses[i];
s_collateralTokens.push(tokenAddresses[i]);
}
i_dsc = DecentralizedStableCoin(dscAddress);
}tags: bughunting, codehawks, smart contract, solidity, double spending, depegging, stablecoin, lack-of-input-validation-vul, severity medium