feat: finish challenge
Some checks failed
Lint / ci (lts/*, ubuntu-latest) (push) Has been cancelled

This commit is contained in:
han
2026-01-23 19:56:48 +07:00
parent e7b2a69f2a
commit 2ad0e8c238
9 changed files with 2413 additions and 20 deletions

View File

@@ -15,6 +15,8 @@ contract DEX {
/* ========== GLOBAL VARIABLES ========== */
IERC20 token; //instantiates the imported contract
uint256 public totalLiquidity;
mapping (address => uint256) public liquidity;
/* ========== EVENTS ========== */
@@ -57,13 +59,27 @@ contract DEX {
* @return totalLiquidity is the number of LPTs minting as a result of deposits made to DEX contract
* NOTE: since ratio is 1:1, this is fine to initialize the totalLiquidity (wrt to balloons) as equal to eth balance of contract.
*/
function init(uint256 tokens) public payable returns (uint256) {}
function init(uint256 tokens) public payable returns (uint256) {
require(totalLiquidity == 0, "DEX: init - already has liquidity");
totalLiquidity = address(this).balance;
liquidity[msg.sender] = totalLiquidity;
require(token.transferFrom(msg.sender, address(this), tokens), "DEX: init - transfer did not transact");
return totalLiquidity;
}
/**
* @notice returns yOutput, or yDelta for xInput (or xDelta)
* @dev Follow along with the [original tutorial](https://medium.com/@austin_48503/%EF%B8%8F-minimum-viable-exchange-d84f30bd0c90) Price section for an understanding of the DEX's pricing model and for a price function to add to your contract. You may need to update the Solidity syntax (e.g. use + instead of .add, * instead of .mul, etc). Deploy when you are done.
*/
function price(uint256 xInput, uint256 xReserves, uint256 yReserves) public pure returns (uint256 yOutput) {}
function price(uint256 xInput, uint256 xReserves, uint256 yReserves) public pure returns (uint256 yOutput) {
uint256 feePercentage = 997;
uint256 feeDenominator = 1000;
uint256 xInputAfterFee = xInput * feePercentage;
uint256 numerator = xInputAfterFee * yReserves;
uint256 denominator = (xReserves * feeDenominator) + xInputAfterFee;
return (numerator / denominator);
}
/**
* @notice returns liquidity for a user.
@@ -71,17 +87,41 @@ contract DEX {
* NOTE: if you are using a mapping liquidity, then you can use `return liquidity[lp]` to get the liquidity for a user.
* NOTE: if you will be submitting the challenge make sure to implement this function as it is used in the tests.
*/
function getLiquidity(address lp) public view returns (uint256) {}
function getLiquidity(address lp) public view returns (uint256) {
return liquidity[lp];
}
/**
* @notice sends Ether to DEX in exchange for $BAL
*/
function ethToToken() public payable returns (uint256 tokenOutput) {}
function ethToToken() public payable returns (uint256 tokenOutput) {
require(msg.value > 0, "cannot swap 0 ETH");
uint256 ethReserve = address(this).balance - msg.value;
uint256 tokenReserve = token.balanceOf(address(this));
tokenOutput = price(msg.value, ethReserve, tokenReserve);
require(token.transfer(msg.sender, tokenOutput), "ethToToken(): reverted swap.");
emit EthToTokenSwap(msg.sender, tokenOutput, msg.value);
return tokenOutput;
}
/**
* @notice sends $BAL tokens to DEX in exchange for Ether
*/
function tokenToEth(uint256 tokenInput) public returns (uint256 ethOutput) {}
function tokenToEth(uint256 tokenInput) public returns (uint256 ethOutput) {
require(tokenInput > 0, "cannot swap 0 tokens");
require(token.balanceOf(msg.sender) >= tokenInput, "insufficient token balance");
require(token.allowance(msg.sender, address(this)) >= tokenInput, "insufficient allowance");
uint256 ethReserve = address(this).balance;
uint256 tokenReserve = token.balanceOf(address(this));
ethOutput = price(tokenInput, tokenReserve, ethReserve);
require(token.transferFrom(msg.sender, address(this), tokenInput), "tokenToEth(): reverted swap.");
(bool success,) = msg.sender.call{value: ethOutput}("");
require(success, "tokenToEth: reverted in transferring eth to you!");
emit TokenToEthSwap(msg.sender, tokenInput, ethOutput);
return ethOutput;
}
/**
* @notice allows deposits of $BAL and $ETH to liquidity pool
@@ -89,11 +129,45 @@ contract DEX {
* NOTE: user has to make sure to give DEX approval to spend their tokens on their behalf by calling approve function prior to this function call.
* NOTE: Equal parts of both assets will be removed from the user's wallet with respect to the price outlined by the AMM.
*/
function deposit() public payable returns (uint256 tokensDeposited) {}
function deposit() public payable returns (uint256 tokensDeposited) {
require(msg.value > 0, "Must send value when depositing");
uint256 ethReserve = address(this).balance - msg.value;
uint256 tokenReserve = token.balanceOf(address(this));
uint256 tokenDeposit;
tokenDeposit = (msg.value * tokenReserve / ethReserve) + 1;
require(token.balanceOf(msg.sender) >= tokenDeposit, "insufficient token balance");
require(token.allowance(msg.sender, address(this)) >= tokenDeposit, "insufficient allowance");
uint256 liquidityMinted = msg.value * totalLiquidity / ethReserve;
liquidity[msg.sender] += liquidityMinted;
totalLiquidity += liquidityMinted;
require(token.transferFrom(msg.sender, address(this), tokenDeposit));
emit LiquidityProvided(msg.sender, liquidityMinted, msg.value, tokenDeposit);
return tokenDeposit;
}
/**
* @notice allows withdrawal of $BAL and $ETH from liquidity pool
* NOTE: with this current code, the msg caller could end up getting very little back if the liquidity is super low in the pool. I guess they could see that with the UI.
*/
function withdraw(uint256 amount) public returns (uint256 ethAmount, uint256 tokenAmount) {}
function withdraw(uint256 amount) public returns (uint256 ethAmount, uint256 tokenAmount) {
require(liquidity[msg.sender] >= amount, "withdraw: sender does not have enough liquidity to withdraw.");
uint256 ethReserve = address(this).balance;
uint256 tokenReserve = token.balanceOf(address(this));
uint256 ethWithdrawn;
ethWithdrawn = amount * ethReserve / totalLiquidity;
uint256 tokenAmount = amount * tokenReserve / totalLiquidity;
liquidity[msg.sender] -= amount;
totalLiquidity -= amount;
(bool sent, ) = payable(msg.sender).call{value: ethWithdrawn}("");
require(sent, "withdraw(): revert in transferring eth to you!");
require(token.transfer(msg.sender, tokenAmount));
emit LiquidityRemoved(msg.sender, amount, tokenAmount, ethWithdrawn);
return (ethWithdrawn, tokenAmount);
}
}