feat: finish challenge
Some checks failed
Lint / ci (lts/*, ubuntu-latest) (push) Has been cancelled
Some checks failed
Lint / ci (lts/*, ubuntu-latest) (push) Has been cancelled
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,19 +50,19 @@ const deployYourContract: DeployFunction = async function (hre: HardhatRuntimeEn
|
||||
const dex = (await hre.ethers.getContract("DEX", deployer)) as DEX;
|
||||
|
||||
// // paste in your front-end address here to get 10 balloons on deploy:
|
||||
// await balloons.transfer("YOUR_FRONTEND_ADDRESS", "" + 10 * 10 ** 18);
|
||||
await balloons.transfer("0x0d76b138023D1B901a155f491CE245736729893a", "" + 10 * 10 ** 18);
|
||||
|
||||
// // uncomment to init DEX on deploy:
|
||||
|
||||
// const dexAddress = await dex.getAddress();
|
||||
// console.log("Approving DEX (" + dexAddress + ") to take Balloons from main account...");
|
||||
// // If you are going to the testnet make sure your deployer account has enough ETH
|
||||
// await balloons.approve(dexAddress, hre.ethers.parseEther("100"));
|
||||
// console.log("INIT exchange...");
|
||||
// await dex.init(hre.ethers.parseEther("5"), {
|
||||
// value: hre.ethers.parseEther("5"),
|
||||
// gasLimit: 200000,
|
||||
// });
|
||||
const dexAddress = await dex.getAddress();
|
||||
console.log("Approving DEX (" + dexAddress + ") to take Balloons from main account...");
|
||||
// If you are going to the testnet make sure your deployer account has enough ETH
|
||||
await balloons.approve(dexAddress, hre.ethers.parseEther("100"));
|
||||
console.log("INIT exchange...");
|
||||
await dex.init(hre.ethers.parseEther("0.01"), {
|
||||
value: hre.ethers.parseEther("0.01"),
|
||||
gasLimit: 200000,
|
||||
});
|
||||
};
|
||||
|
||||
export default deployYourContract;
|
||||
|
||||
1
packages/hardhat/deployments/sepolia/.chainId
Normal file
1
packages/hardhat/deployments/sepolia/.chainId
Normal file
@@ -0,0 +1 @@
|
||||
11155111
|
||||
530
packages/hardhat/deployments/sepolia/Balloons.json
Normal file
530
packages/hardhat/deployments/sepolia/Balloons.json
Normal file
File diff suppressed because one or more lines are too long
434
packages/hardhat/deployments/sepolia/DEX.json
Normal file
434
packages/hardhat/deployments/sepolia/DEX.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user