ProphetSwap is a router contract built to route all trade done through the bot and take a revshare fee that is withdrawable by the team
$ forge build
$ forge test
$ forge fmt
$ forge snapshot
forge doc --build
forge doc --serve
Inherits: Ownable2Step
This contract interacts with Uniswap V2 to facilitate token swaps and collects a fee on each transaction.
uint256 public totalFeeCollected;
address private constant UNISWAP_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
constructor();
Buys tokens on Uniswap V2 and collects a fee
function ProphetBuy(uint256 amountOutMin, address tokenAddress, uint256 _fee) external payable;
Parameters
Name | Type | Description |
---|---|---|
amountOutMin |
uint256 |
Minimum amount of tokens to receive from the swap |
tokenAddress |
address |
The address of the token to buy |
_fee |
uint256 |
The fee percentage to be collected |
Sells tokens on Uniswap V2 and collects a fee
function ProphetSell(uint256 amountIn, uint256 amountOutMin, address tokenAddress, uint256 _fee) external;
Parameters
Name | Type | Description |
---|---|---|
amountIn |
uint256 |
Amount of tokens to sell |
amountOutMin |
uint256 |
Minimum amount of ETH to receive from the swap |
tokenAddress |
address |
The address of the token to sell |
_fee |
uint256 |
The fee percentage to be collected |
Sells tokens on Uniswap V2 for a specified amount of ETH, collects a fee
function ProphetSmartSell(uint256 amountOut, uint256 amountInMax, address tokenAddress, uint256 _fee) external;
Parameters
Name | Type | Description |
---|---|---|
amountOut |
uint256 |
The exact amount of ETH to receive from the swap |
amountInMax |
uint256 |
The maximum amount of tokens to sell |
tokenAddress |
address |
The address of the token to sell |
_fee |
uint256 |
The fee percentage to be collected in BPS |
Helper function to get the swap path for token to token or ETH to token swaps
function getPathForTokenToToken(bool swapETH, address _tokenOut) private pure returns (address[] memory);
Parameters
Name | Type | Description |
---|---|---|
swapETH |
bool |
Indicates whether the swap involves ETH |
_tokenOut |
address |
The address of the output token |
Returns
Name | Type | Description |
---|---|---|
<none> |
address[] |
path The swap path as an array of addresses |
Allows the contract owner to withdraw tokens from the contract
function withdraw(address _token) external onlyOwner;
Parameters
Name | Type | Description |
---|---|---|
_token |
address |
The token address to withdraw |
Allows the contract owner to withdraw ETH from the contract
function withdrawETH() external;
Fallback function to receive ETH
receive() external payable;
Event emitted after collecting a fee
event ProphetFee(address indexed sender, uint256 amount);
Custom Errors for the contract
error InvalidAmount();
error InvalidOutputAmount();
error InvalidFeeAmount();
error InvalidToken();
error TransferFailed();
- Potential Issues with Using block.timestamp as the Deadline for AMM Swaps
- Centralizaiont risks if keys are compromised
Frontrunning and Sandwich attacks a threat to the security of an AMMs. In the current implementation, the block.timestamp
is used as the deadline parameter.
Since block.timestamp
aligns with the current timestamp when included in a block by the miner, this opens an opportunity for miners game the system as the cost of a user. A malicious miner can withhold the transaction from being mined until it incurs the maximum slippage. Alternatively, they may exploit the transaction later to execute a sandwich attack.
Similar instances have been reported in auditing contests:
Code 423n4 - 2022-11-paraspace-findings
Sherlock Audit - 2023-01-ajna-judging
It is advisable that the deadline parameter of 3600 + block.timestamp
be revised to deem if it is necessary or not. The deadline could be calculated on the frontend and sent to the contract as an argument. For example you can get the current time using the js date()
method add 3600 to and it pass it as the deadline
parameter. This way it cannot be manipulate by a miner.
Many core functions including withdrawETH
and withdrawTokens
withdraw all the funds from fees to a revShare
address. If for whatever reason this address is compromised it could lead to loss of funds to the team.
Currently there aren't many way to mitigate against this besides ensuring that this address is a multi sig. If one of the keys get compromised the funds will still be safe and retrievable by the owners.