sherlock-2025-04-burve-h02
[H-02] Incorrect implementation of ERC4626ViewAdjustor
Summary
정규화 또는 실제 토큰 수를 계산하는 함수가 잘못 구현되어 잘못된 양의 토큰을 이용한다.
Keyword
bug, arithmetic error, erc4626
Vulnerability
Adjustor 컨트랙트는 연동할 토큰을 실제 양을 정규화한 값으로 변환하거나 정규화 값을 실제 토큰양으로 변환하는 기능을 제공한다. 정규화된 값은 프로토콜 내에서 토큰 수를 계산할 때 이용한다. 예를 들어 6 decimals 토큰과 8 decimals 토큰을 이용한다면 내부에서 계산할 때는 이를 정규화하여 18 decimals로 스케일링해 사용한다.
그 중 E4626ViewAdjustor는 ERC4626 share 토큰의 양을 정규화 또는 실제화 한다. stETH와 같이 ERC4626으로 구현된 토큰을 이용할 때 이 Adjustor를 이용할 것이다. 그런데 이 컨트랙트의 toNominal과 toReal의 구현이 올바르지 않아 잘못된 값을 리턴, 잘못된 양의 토큰을 이용하게 된다.
다음은 E4626ViewAdjustor의 함수이다. toNominal 함수는 정규화된 토큰 양을 리턴해야 하고, toReal 함수는 실제 토큰 양을 리턴해야 한다. 그런데 toNominal 함수는 파라미터로 주어진 양만큼의 ERC4626의 share를 리턴하고, toReal는 ERC4626의 에셋 토큰 양을 리턴한다. 이는 Burve 프로토콜 내에서 사용하기 위한 정규화와는 아무런 상관이 없는, 완전히 잘못된 구현이다.
function toNominal(
address token,
uint256 real,
bool
) external view returns (uint256 nominal) {
IERC4626 vault = getVault(token);
return vault.convertToShares(real);
}
function toReal(
address token,
uint256 nominal,
bool
) external view returns (uint256 real) {
IERC4626 vault = getVault(token);
return vault.convertToAssets(nominal);
}위 함수의 사용 예를 보자. 다음은 토큰을 풀에 입금할 때 호출되는 로직이다. toReal 을 호출하여 실제로 필요한 토큰의 양을 계산한다. 그런데 E4626ViewAdjustor.toReal는 예치해야 하는 토큰의 에셋 토큰 양을 리턴한다.(stETH라면 정규화된 값을 share로 하는 ETH의 양을 리턴) 정말로 E4626ViewAdjustor를 사용할 때 에셋 토큰을 예치하는 게 목적이라면 IERC4626(token).asset() 토큰을 이동해야 한다.
uint256 realNeeded = AdjustorLib.toReal(
@> token,
requiredNominal[i],
true
);
requiredBalances[i] = realNeeded;
TransferHelper.safeTransferFrom(
@> token,
msg.sender,
address(this),
realNeeded
);Impact
E4626ViewAdjustor 를 사용하면 잘못된 양의 토큰을 이용하게 된다.
Mitigation
E4626ViewAdjustor 를 목적에 맞게 고친다.(버그로 인해 코드가 모호하여 무엇이 개발 목적인지 잘 모르겠다)
tags: bughunting, burve, smart contract, solidity, erc4626, arithmetic error, severity high