Skip to content

Commit

Permalink
Merge branch 'dev' into feat/unchecked-bnum
Browse files Browse the repository at this point in the history
  • Loading branch information
wei3erHase authored May 14, 2024
2 parents 1e4fa48 + cebb5dc commit 5d354d3
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 2 deletions.
2 changes: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ src = 'src/interfaces/'

[fuzz]
runs = 1000
max_test_rejects = 1000000
max_test_rejects = 1_000_000

[rpc_endpoints]
mainnet = "${MAINNET_RPC}"
Expand Down
111 changes: 110 additions & 1 deletion test/unit/BPool.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {BPool} from 'contracts/BPool.sol';
import {MockBPool} from 'test/smock/MockBPool.sol';

import {BConst} from 'contracts/BConst.sol';
import {BMath} from 'contracts/BMath.sol';
import {IERC20} from 'contracts/BToken.sol';
import {Test} from 'forge-std/Test.sol';
import {LibString} from 'solmate/utils/LibString.sol';
Expand Down Expand Up @@ -65,6 +66,10 @@ abstract contract BasePoolTest is Test, BConst, Utils {
bPool.set__publicSwap(_isPublicSwap);
}

function _setSwapFee(uint256 _swapFee) internal {
bPool.set__swapFee(_swapFee);
}

function _setFinalize(bool _isFinalized) internal {
bPool.set__finalized(_isFinalized);
}
Expand Down Expand Up @@ -500,7 +505,111 @@ contract BPool_Unit_ExitPool is BasePoolTest {
function test_Emit_LogCall() private view {}
}

contract BPool_Unit_SwapExactAmountIn is BasePoolTest {
contract BPool_Unit_SwapExactAmountIn is BasePoolTest, BMath {
address tokenIn;
address tokenOut;

struct SwapExactAmountIn_FuzzScenario {
uint256 tokenAmountIn;
uint256 tokenInBalance;
uint256 tokenInDenorm;
uint256 tokenOutBalance;
uint256 tokenOutDenorm;
uint256 swapFee;
}

function _setValues(SwapExactAmountIn_FuzzScenario memory _fuzz) internal {
tokenIn = tokens[0];
tokenOut = tokens[1];

// Create mocks for tokenIn and tokenOut (only use the first 2 tokens)
_mockTransferFrom(tokenIn);
_mockTransfer(tokenOut);

// Set balances
_setRecord(
tokenIn,
BPool.Record({
bound: true,
index: 0, // NOTE: irrelevant for this method
denorm: _fuzz.tokenInDenorm,
balance: _fuzz.tokenInBalance
})
);
_setRecord(
tokenOut,
BPool.Record({
bound: true,
index: 0, // NOTE: irrelevant for this method
denorm: _fuzz.tokenOutDenorm,
balance: _fuzz.tokenOutBalance
})
);

// Set swapFee
_setSwapFee(_fuzz.swapFee);
// Set public swap
_setPublicSwap(true);
// Set finalize
_setFinalize(true);
}

function _assumeHappyPath(SwapExactAmountIn_FuzzScenario memory _fuzz) internal view {
// safe bound assumptions
_fuzz.tokenInDenorm = bound(_fuzz.tokenInDenorm, MIN_WEIGHT, MAX_WEIGHT);
_fuzz.tokenOutDenorm = bound(_fuzz.tokenOutDenorm, MIN_WEIGHT, MAX_WEIGHT);
_fuzz.swapFee = bound(_fuzz.swapFee, MIN_FEE, MAX_FEE);

// min
vm.assume(_fuzz.tokenInBalance >= MIN_BALANCE);
vm.assume(_fuzz.tokenOutBalance >= MIN_BALANCE);

// max - calcSpotPrice (spotPriceBefore)
vm.assume(_fuzz.tokenInBalance < type(uint256).max / _fuzz.tokenInDenorm);
vm.assume(_fuzz.tokenOutBalance < type(uint256).max / _fuzz.tokenOutDenorm);

// max - calcSpotPrice (spotPriceAfter)
vm.assume(_fuzz.tokenAmountIn < type(uint256).max - _fuzz.tokenInBalance);
vm.assume(_fuzz.tokenInBalance + _fuzz.tokenAmountIn < type(uint256).max / _fuzz.tokenInDenorm);

// internal calculation for calcSpotPrice
uint256 _numer = bdiv(_fuzz.tokenInBalance, _fuzz.tokenInDenorm);
uint256 _denom = bdiv(_fuzz.tokenOutBalance, _fuzz.tokenOutDenorm);
uint256 _ratio = bdiv(_numer, _denom);
uint256 _scale = bdiv(BONE, bsub(BONE, _fuzz.swapFee));
vm.assume(_ratio < type(uint256).max / _scale);

// MAX_IN_RATIO
vm.assume(_fuzz.tokenAmountIn <= bmul(_fuzz.tokenInBalance, MAX_IN_RATIO));

// L338 BPool.sol
uint256 _spotPriceBefore = calcSpotPrice(
_fuzz.tokenInBalance, _fuzz.tokenInDenorm, _fuzz.tokenOutBalance, _fuzz.tokenOutDenorm, _fuzz.swapFee
);
uint256 _tokenAmountOut = calcOutGivenIn(
_fuzz.tokenInBalance,
_fuzz.tokenInDenorm,
_fuzz.tokenOutBalance,
_fuzz.tokenOutDenorm,
_fuzz.tokenAmountIn,
_fuzz.swapFee
);
vm.assume(_tokenAmountOut > BONE);
vm.assume(bmul(_spotPriceBefore, _tokenAmountOut) <= _fuzz.tokenAmountIn);
}

modifier happyPath(SwapExactAmountIn_FuzzScenario memory _fuzz) {
_assumeHappyPath(_fuzz);
_setValues(_fuzz);
_;
}

function test_HappyPath(SwapExactAmountIn_FuzzScenario memory _fuzz) public happyPath(_fuzz) {
uint256 _maxPrice = type(uint256).max;
uint256 _minAmountOut = 0;
bPool.swapExactAmountIn(tokenIn, _fuzz.tokenAmountIn, tokenOut, _minAmountOut, _maxPrice);
}

function test_Revert_NotBoundTokenIn() private view {}

function test_Revert_NotBoundTokenOut() private view {}
Expand Down

0 comments on commit 5d354d3

Please sign in to comment.