code4rena-2023-06-angle-protocol-m06
[M-06] Interest is not accrued before parameters are updated in SavingsVest
Summary
이자 발행의 조건이 되었을 때, 이자를 발행하기 전에(accrue 호출 전에) setParams 함수를 호출한다면 변경된 변수를 기반으로 이자가 계산된다. 따라서 홀더가 잘못 계산된 이자를 받는다. 변경 전에 먼저 과거의 이자를 정산해야 한다는 의미.
Keyword
bug, logic flaw
Vulnerability
SavingsVest 컨트랙트에 스테이블 코인을 예치해두면 Transmuter 프로토콜에서 과담보 상태가 되었을 시 이자를 얻을 수 있다. 이 이자는 SavingsVest.accrue 함수를 통해 발행된다.
이익에 영향을 끼치는 요소는 다음과 같다.
- protocolSafetyFee: SavingsVest의 수수료
- vestingPeriod: 이자가 lock되어 있는 기간
이 두 요소는 setParams 함수를 통해 관리자에 의해 변경 가능하다.
function setParams(bytes32 what, uint64 param) external onlyGuardian {
if (param > BASE_9) revert InvalidParam();
else if (what == "PF") protocolSafetyFee = param;
else if (what == "VP") vestingPeriod = uint32(param);
else if (what == "UD") updateDelay = uint32(param);
else if (what == "P") paused = uint8(param);
else revert InvalidParam();
emit FiledUint64(param, what);
}이자 발행의 조건이 되었을 때, 이자를 발행하기 전에(accrue 호출 전에) setParams 함수를 호출한다면 아직 발행되지 않은 이자에도 적용이 된다.
protocolSafetyFee를 올려 예금자 몫의 이자를 줄이거나, vestingPeriod를 올려 이자가 좀 더 오래 lock 되도록 하고 수익률이 떨어지게 할 수 있다.
Impact
홀더가 잘못 계산된 이자를 받는다.
Mitigation
setParams를 호출하는 시점에 아직 발행되지 않은 이자가 있다면 먼저 이 이자를 발행해준 뒤 설정을 변경한다.
function setParams(bytes32 what, uint64 param) external onlyGuardian {
if (param > BASE_9) revert InvalidParam();
- else if (what == "PF") protocolSafetyFee = param;
- else if (what == "VP") vestingPeriod = uint32(param);
else if (what == "UD") updateDelay = uint32(param);
else if (what == "P") paused = uint8(param);
- else revert InvalidParam();
+ else {
+ // Interest must be accrued with the current parameters before setting new `protocolSafetyFee`
+ // and `vestingPeriod`
+ accrue();
+ if (what == "PF") protocolSafetyFee = param;
+ else if (what == "VP") vestingPeriod = uint32(param);
+ else revert InvalidParam();
+ }
emit FiledUint64(param, what);
}tags: bughunting, angle protocol, smart contract, solidity, stablecoin, logic flaw, severity medium