Skip to content

Commit

Permalink
fix #8 (#9)
Browse files Browse the repository at this point in the history
also add gas-report command
  • Loading branch information
0xduality authored Oct 19, 2022
1 parent 09a69c6 commit 68c5db6
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 25 deletions.
4 changes: 3 additions & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ remappings = [
"@solbase=lib/solbase/src/"
]

gas_reports = ["Helios", "HeliosReference"]

[profile.intense.fuzz]
runs = 10000
runs = 10000
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"test": "forge clean && forge test",
"cov": "forge clean && forge coverage --report lcov && genhtml -o report lcov.info",
"snapshot": "forge clean && forge snapshot",
"gas-report": "forge clean && forge test --gas-report",
"lint": "prettier --print-width 120 --write src/**/*.sol && prettier --print-width 120 --write src/*.sol"
}
}
26 changes: 15 additions & 11 deletions src/Helios.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import {OwnedThreeStep} from "@solbase/auth/OwnedThreeStep.sol";
import {SafeTransferLib} from "@solbase/utils/SafeTransferLib.sol";
import {FixedPointMathLib} from "@solbase/utils/FixedPointMathLib.sol";
import {SafeMulticallable} from "@solbase/utils/SafeMulticallable.sol";
import {ReentrancyGuard} from "@solbase/utils/ReentrancyGuard.sol";
import {ERC1155, ERC1155TokenReceiver} from "@solbase/tokens/ERC1155.sol";

/// @notice ERC1155 vault with router and liquidity pools.
/// @author z0r0z.eth (SolDAO)
contract Helios is OwnedThreeStep(tx.origin), SafeMulticallable, ERC1155, ERC1155TokenReceiver {
contract Helios is OwnedThreeStep(tx.origin), ReentrancyGuard, SafeMulticallable, ERC1155, ERC1155TokenReceiver {
constructor() payable {} // Clean deployment.

/// -----------------------------------------------------------------------
Expand Down Expand Up @@ -171,7 +172,7 @@ contract Helios is OwnedThreeStep(tx.origin), SafeMulticallable, ERC1155, ERC115
});

// Swapper dictates output LP.
liq = swapper.addLiquidity(id, token0amount, token1amount);
(liq, , ) = swapper.addLiquidity(id, token0amount, token1amount);

_mint(to, id, liq, data);

Expand All @@ -195,24 +196,27 @@ contract Helios is OwnedThreeStep(tx.origin), SafeMulticallable, ERC1155, ERC115
uint256 token0amount,
uint256 token1amount,
bytes calldata data
) external payable returns (uint256 liq) {
) external payable nonReentrant returns (uint256 liq) {
require(id <= totalSupply, "Helios: PAIR_DOESNT_EXIST");

Pair storage pair = pairs[id];

// If base is address(0), assume native token and overwrite amount.
if (pair.token0 == address(0)) {
token0amount = msg.value;
if (pair.token0 == address(0)) token0amount = msg.value;

// Swapper dictates output LP and adjustments to token amounts
(liq, token0amount, token1amount) = pair.swapper.addLiquidity(id, token0amount, token1amount);

pair.token1.safeTransferFrom(msg.sender, address(this), token1amount);
// We know the exact amounts, now transfer and/or refund any ETH
if (pair.token0 == address(0)) {
if (msg.value > token0amount) {
(bool success, ) = payable(msg.sender).call{value: msg.value - token0amount}("");
require(success, "Helios: REFUND_FAILED");
}
} else {
pair.token0.safeTransferFrom(msg.sender, address(this), token0amount);

pair.token1.safeTransferFrom(msg.sender, address(this), token1amount);
}

// Swapper dictates output LP.
liq = pair.swapper.addLiquidity(id, token0amount, token1amount);
pair.token1.safeTransferFrom(msg.sender, address(this), token1amount);

require(liq != 0, "Helios: INSUFFICIENT_LIQUIDITY_MINTED");

Expand Down
32 changes: 21 additions & 11 deletions src/HeliosReference.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,19 @@ import {OwnedThreeStep} from "@solbase/auth/OwnedThreeStep.sol";
import {SafeTransferLib} from "@solbase/utils/SafeTransferLib.sol";
import {FixedPointMathLib} from "@solbase/utils/FixedPointMathLib.sol";
import {SafeMulticallable} from "@solbase/utils/SafeMulticallable.sol";
import {ReentrancyGuard} from "@solbase/utils/ReentrancyGuard.sol";
import {ERC1155, ERC1155TokenReceiver} from "@solbase/tokens/ERC1155.sol";

/// @notice ERC1155 vault with router and liquidity pools.
/// @dev Reference implementation (emphasizes clarity, deemphasizes gas cost)
/// @author z0r0z.eth (SolDAO)
contract HeliosReference is OwnedThreeStep(tx.origin), SafeMulticallable, ERC1155, ERC1155TokenReceiver {
contract HeliosReference is
OwnedThreeStep(tx.origin),
ReentrancyGuard,
SafeMulticallable,
ERC1155,
ERC1155TokenReceiver
{
constructor() payable {} // Clean deployment.

/// -----------------------------------------------------------------------
Expand Down Expand Up @@ -172,7 +179,7 @@ contract HeliosReference is OwnedThreeStep(tx.origin), SafeMulticallable, ERC115
});

// Swapper dictates output LP.
liq = swapper.addLiquidity(id, token0amount, token1amount);
(liq, , ) = swapper.addLiquidity(id, token0amount, token1amount);

_mint(to, id, liq, data);

Expand All @@ -196,24 +203,27 @@ contract HeliosReference is OwnedThreeStep(tx.origin), SafeMulticallable, ERC115
uint256 token0amount,
uint256 token1amount,
bytes calldata data
) external payable returns (uint256 liq) {
) external payable nonReentrant returns (uint256 liq) {
require(id <= totalSupply, "Helios: PAIR_DOESNT_EXIST");

Pair storage pair = pairs[id];

// If base is address(0), assume native token and overwrite amount.
if (pair.token0 == address(0)) {
token0amount = msg.value;
if (pair.token0 == address(0)) token0amount = msg.value;

// Swapper dictates output LP and adjustments to token amounts
(liq, token0amount, token1amount) = pair.swapper.addLiquidity(id, token0amount, token1amount);

pair.token1.safeTransferFrom(msg.sender, address(this), token1amount);
// We know the exact amounts, now transfer and/or refund any ETH
if (pair.token0 == address(0)) {
if (msg.value > token0amount) {
(bool success, ) = payable(msg.sender).call{value: msg.value - token0amount}("");
require(success, "Helios: REFUND_FAILED");
}
} else {
pair.token0.safeTransferFrom(msg.sender, address(this), token0amount);

pair.token1.safeTransferFrom(msg.sender, address(this), token1amount);
}

// Swapper dictates output LP.
liq = pair.swapper.addLiquidity(id, token0amount, token1amount);
pair.token1.safeTransferFrom(msg.sender, address(this), token1amount);

require(liq != 0, "Helios: INSUFFICIENT_LIQUIDITY_MINTED");

Expand Down
8 changes: 7 additions & 1 deletion src/interfaces/IHelios.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ interface IHelios {
uint256 id,
uint256 token0amount,
uint256 token1amount
) external returns (uint256 liq);
)
external
returns (
uint256 liq,
uint256 amount0,
uint256 amount1
);

function removeLiquidity(uint256 id, uint256 liq) external returns (uint256 amount0out, uint256 amount1out);

Expand Down
14 changes: 13 additions & 1 deletion src/swappers/XYKswapper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,15 @@ contract XYKswapper is ReentrancyGuard {
uint256 id,
uint256 token0amount,
uint256 token1amount
) external nonReentrant returns (uint256 liq) {
)
external
nonReentrant
returns (
uint256 liq,
uint256 amount0,
uint256 amount1
)
{
IHelios.Pair memory pair = IHelios(msg.sender).pairs(id);

uint256 reserve0 = pair.reserve0;
Expand All @@ -49,8 +57,12 @@ contract XYKswapper is ReentrancyGuard {

if (totalSupply == 0) {
liq = (token0amount * token1amount).sqrt() - MIN_LP;
amount0 = token0amount;
amount1 = token1amount;
} else {
liq = min((token0amount * totalSupply) / reserve0, (token1amount * totalSupply) / reserve1);
amount0 = (reserve0 * liq) / totalSupply;
amount1 = (reserve1 * liq) / totalSupply;
}

require(liq != 0, "XYKswapper: INSUFFICIENT_LIQUIDITY_MINTED");
Expand Down
17 changes: 17 additions & 0 deletions src/test/Helios.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,23 @@ contract HeliosTest is ERC1155TokenReceiver, Test {
helios.createPair(address(this), token0, token1, 1_000 ether, 1_000 ether, xykSwapper, 1, "");
}

function testAddLiquidity() public payable {
(uint256 id, uint256 c) = helios.createPair(
address(this),
token0,
token1,
1_000 ether,
1_000 ether,
xykSwapper,
1,
""
);
uint256 b = helios.addLiquidity(address(this), id, 1_000 ether, 1_000 ether, "");
uint256 a = helios.addLiquidity(address(this), id, 1_000 ether, 1_000 ether, "");
require(a == b, "a!=b");
require(b == c, "b!=c");
}

function testXYKpairSwap(uint256 amountIn) public payable {
uint256 b0 = MockERC20(token0).balanceOf(address(this));
vm.assume(amountIn > 100000 && amountIn < b0);
Expand Down
17 changes: 17 additions & 0 deletions src/test/HeliosReference.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,23 @@ contract HeliosReferenceTest is ERC1155TokenReceiver, Test {
helios.createPair(address(this), token0, token1, 1_000 ether, 1_000 ether, xykSwapper, 1, "");
}

function testAddLiquidity() public payable {
(uint256 id, uint256 c) = helios.createPair(
address(this),
token0,
token1,
1_000 ether,
1_000 ether,
xykSwapper,
1,
""
);
uint256 b = helios.addLiquidity(address(this), id, 1_000 ether, 1_000 ether, "");
uint256 a = helios.addLiquidity(address(this), id, 1_000 ether, 1_000 ether, "");
require(a == b, "a!=b");
require(b == c, "b!=c");
}

function testXYKpairSwap(uint256 amountIn) public payable {
uint256 b0 = MockERC20(token0).balanceOf(address(this));
vm.assume(amountIn > 100000 && amountIn < b0);
Expand Down

0 comments on commit 68c5db6

Please sign in to comment.