code4rena-2021-06-pooltogether-h03
[H-03] BadgerYieldSource balanceOfToken share calculation seems wrong
Summary
외부 컨트랙트를 이용하는데, 잘못 연동하여 balanceOfToken 함수가 실제보다 작은 값을 리턴한다.
Keyword
bug, logic flaw
Vulnerability
BadgerYieldSource는 외부 투자 풀(Badger Sett Vaults)에 토큰을 예치하고 관리하는 컨트랙트이다. BadgerYieldSource.balanceOfToken 함수는 addr가 투자에 사용한 Underlying 토큰 수를 리턴해야 한다.
사용하는 외부 투자 풀인 Badger Sett Vaults는 badger 토큰을 예치하는 풀이다. 토큰이 예치되면 Badger Sett Vaults는 ERC20 영수증 토큰을 민팅해준다. balanceOfToken 함수는 addr가 소유한 badgerSett 토큰/ 전체 badgerSett 토큰 으로 비율을 구하고, 여기에 Badger Sett Vaults 컨트랙트에 예치된 badger 토큰 수를 곱하면 addr의 badger 지분을 계산할 수 있다는 논리를 따른다.
참고로 balances[addr]에는 유저가 투자 후 발급받은 badgerSett 개수가 저장되어 있다.
/// @notice Returns the total balance (in asset tokens). This includes the deposits and interest.
/// @return The underlying balance of asset tokens
function balanceOfToken(address addr) public override returns (uint256) {
if (balances[addr] == 0) return 0;
uint256 totalShares = badgerSett.totalSupply();
uint256 badgerSettBadgerBalance = badger.balanceOf(address(badgerSett));
return (balances[addr].mul(badgerSettBadgerBalance).div(totalShares));
}이 로직은 일반적으로는 맞겠지만, Badger Sett Vaults의 특징으로 인해 맞지 않는다. Badger의 docs를 보면 Badger Sett Vaults는 예치된 badger를 일부 옮겨 보관한다고 적혀있다.
Typically, a Sett will keep a small portion of deposited funds in reserve to handle small withdrawals cheaply
따라서, badger.balanceOf(address(badgerSett)) 는 실제로 예치된 badger 토큰 양보다 작은 양을 리턴한다. 이로 인해 BadgerYieldSource.balanceOfToken 함수는 실제보다 작은 양을 리턴한다.
Impact
balanceOfToken 함수를 사용하는 balanceOf 함수에서 실제보다 작은 값을 리턴한다. 이 값을 기반으로 계산한다면 시스템 연동 시 추가 오류가 발생할 것이다.
Mitigation
badger.balanceOf(address(badgerSett)) 대신 Badger Sett Vaults에서 제공하는 badgerSett.balance() 함수를 사용한다.
tags: bughunting, pooltogether, smart contract, solidity, logic flaw, badger finance, severity high