Omniscia AmpleSense Audit

Pioneer1Vault Manual Review Findings

Pioneer1Vault Manual Review Findings

PVT-01M: Redundant Execution Path

TypeSeverityLocation
Logical FaultMinorPioneer1Vault.sol:L55, L56, L60, L68

Description:

The _rebase function will attempt to evaluate the optimal amount to sell via the trader based on the AMPL balance's proximity to the CAP threshold, however, an additional check is imposed beyond the sale that ensures the balance of the contract remains at or above the SELL_THRESHOLD.

Example:

contracts/Pioneer1Vault.sol
45function _rebase(uint256 old_supply, uint256 new_supply) internal override {
46 require(address(trader) != address(0), "Pioneer1Vault: trader not set");
47 uint256 new_balance = _ampl_token.balanceOf(address(this));
48 require(new_balance > SELL_THRESHOLD, "Pioneer1Vault: Threshold isnt reached yet"); //needs to be checked or else _toSell fails
49 if(new_supply > old_supply) {
50 //only for positive rebases
51 uint256 balance = _ampl_token.balanceOf(address(this));
52
53 uint256 change_ratio_18digits = old_supply.mul(10**18).divDown(new_supply);
54 uint256 surplus = new_balance.sub(new_balance.mul(change_ratio_18digits).divDown(10**18));
55 uint256 to_sell = _toSell(surplus);
56 _ampl_token.approve(address(trader), to_sell);
57
58 trader.sellAMPLForEth(to_sell);
59 //this checks that after the sale we're still above threshold
60 require(_ampl_token.balanceOf(address(this)) >= SELL_THRESHOLD, "Pioneer1Vault: Threshold isnt reached yet");
61 stakingContractEth.distribute{value : address(this).balance}(0, address(this));
62 }
63}
64
65function _toSell(uint256 amount) internal view returns (uint256) {
66 uint256 ampl_balance = _ampl_token.balanceOf(address(this));
67 uint256 percentage = (END_PERCENT - START_PERCENT).mul(Math.min(ampl_balance, CAP).sub(SELL_THRESHOLD)).divDown(CAP.sub(SELL_THRESHOLD)) + START_PERCENT;
68 return percentage.mul(amount).divDown(100);
69}

Recommendation:

As the trader can at most use the amount of tokens approved to it via the _toSell calculation, we advise the _toSell function itself to incorporate this limit and ensure the amount to sell is the minimum between percentage.mul(amount).divDown(100) and _ampl_token.balanceOf(address(this)) - SELL_THRESHOLD to ensure the require check is not necessary and the code executes optimally at all times.

Alleviation:

The Amplesense considered this exhibit but opted not to apply a remediation for it in the current iteration of the codebase to avoid adjusting core contract logic at this point in the code's development.