Bnke0x0
medium
sellPrincipalToken, buyPrincipalToken, sellUnderlying, buyUnderlying uses pool funds but pays msg.sender
sellPrincipalToken, buyPrincipalToken, sellUnderlying, buyUnderlying are all unpermissioned and use marketplace funds to complete the action but send the resulting tokens to msg.sender. This means that any address can call these functions and steal the resulting funds.
Fund loss from the marketplace
https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Marketplace.sol#L285-L425
'function sellPrincipalToken(
address u,
uint256 m,
uint128 a,
uint128 s
) external returns (uint128) {
// Get the pool for the market
IPool pool = IPool(pools[u][m]);
// Preview amount of underlying received by selling `a` PTs
uint256 expected = pool.sellFYTokenPreview(a);
if (expected < s) {
revert Exception(16, expected, s, address(0), address(0));
}
// Transfer the principal tokens to the pool
Safe.transferFrom(
IERC20(address(pool.fyToken())),
msg.sender,
address(pool),
a
);
// Execute the swap
uint128 received = pool.sellFYToken(msg.sender, uint128(expected));
emit Swap(u, m, address(pool.fyToken()), u, received, a, msg.sender);
return received;
}
/// @notice buys the PT for the underlying via the pool
/// @notice determines how many underlying to sell by using the preview
/// @param u address of an underlying asset
/// @param m maturity (timestamp) of the market
/// @param a amount of PTs to be purchased
/// @param s slippage cap, maximum number of underlying that can be sold
/// @return uint128 amount of underlying sold
function buyPrincipalToken(
address u,
uint256 m,
uint128 a,
uint128 s
) external returns (uint128) {
// Get the pool for the market
IPool pool = IPool(pools[u][m]);
// Get the amount of base hypothetically required to purchase `a` PTs
uint128 expected = pool.buyFYTokenPreview(a);
// Verify that the amount needed does not exceed the slippage parameter
if (expected > s) {
revert Exception(16, expected, 0, address(0), address(0));
}
// Transfer the underlying tokens to the pool
Safe.transferFrom(
IERC20(pool.base()),
msg.sender,
address(pool),
expected
);
// Execute the swap to purchase `a` base tokens
uint128 spent = pool.buyFYToken(msg.sender, a, 0);
emit Swap(u, m, u, address(pool.fyToken()), a, spent, msg.sender);
return spent;
}
/// @notice sells the underlying for the PT via the pool
/// @param u address of an underlying asset
/// @param m maturity (timestamp) of the market
/// @param a amount of underlying to sell
/// @param s slippage cap, minimum number of PTs that must be received
/// @return uint128 amount of PT purchased
function sellUnderlying(
address u,
uint256 m,
uint128 a,
uint128 s
) external returns (uint128) {
// Get the pool for the market
IPool pool = IPool(pools[u][m]);
// Get the number of PTs received for selling `a` underlying tokens
uint128 expected = pool.sellBasePreview(a);
// Verify slippage does not exceed the one set by the user
if (expected < s) {
revert Exception(16, expected, 0, address(0), address(0));
}
// Transfer the underlying tokens to the pool
Safe.transferFrom(IERC20(pool.base()), msg.sender, address(pool), a);
// Execute the swap
uint128 received = pool.sellBase(msg.sender, expected);
emit Swap(u, m, u, address(pool.fyToken()), received, a, msg.sender);
return received;
}
/// @notice buys the underlying for the PT via the pool
/// @notice determines how many PTs to sell by using the preview
/// @param u address of an underlying asset
/// @param m maturity (timestamp) of the market
/// @param a amount of underlying to be purchased
/// @param s slippage cap, maximum number of PTs that can be sold
/// @return uint128 amount of PTs sold
function buyUnderlying(
address u,
uint256 m,
uint128 a,
uint128 s
) external returns (uint128) {
// Get the pool for the market
IPool pool = IPool(pools[u][m]);
// Get the amount of PTs hypothetically required to purchase `a` underlying
uint256 expected = pool.buyBasePreview(a);
// Verify that the amount needed does not exceed the slippage parameter
if (expected > s) {
revert Exception(16, expected, 0, address(0), address(0));
}
// Transfer the principal tokens to the pool
Safe.transferFrom(
IERC20(address(pool.fyToken())),
msg.sender,
address(pool),
expected
);
// Execute the swap to purchase `a` underlying tokens
uint128 spent = pool.buyBase(msg.sender, a, 0);
emit Swap(u, m, address(pool.fyToken()), u, a, spent, msg.sender);
return spent;
}
'
Manual Review
All functions should use safetransfer to get funds from msg.sender not from marketplace