Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Challenge 4 migration to extension #245

Merged
merged 7 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
765 changes: 765 additions & 0 deletions README.md

Large diffs are not rendered by default.

753 changes: 753 additions & 0 deletions extension/README.md.args.mjs

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions extension/packages/hardhat/contracts/Balloons.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract Balloons is ERC20 {
constructor() ERC20("Balloons", "BAL") {
_mint(msg.sender, 1000 ether); // mints 1000 balloons!
}
}
120 changes: 120 additions & 0 deletions extension/packages/hardhat/contracts/DEX.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

/**
* @title DEX Template
* @author stevepham.eth and m00npapi.eth
* @notice Empty DEX.sol that just outlines what features could be part of the challenge (up to you!)
* @dev We want to create an automatic market where our contract will hold reserves of both ETH and 🎈 Balloons. These reserves will provide liquidity that allows anyone to swap between the assets.
* NOTE: functions outlined here are what work with the front end of this challenge. Also return variable names need to be specified exactly may be referenced (It may be helpful to cross reference with front-end code function calls).
*/
contract DEX {
/* ========== GLOBAL VARIABLES ========== */

IERC20 token; //instantiates the imported contract

/* ========== EVENTS ========== */

/**
* @notice Emitted when ethToToken() swap transacted
*/
event EthToTokenSwap(
address swapper,
uint256 tokenOutput,
uint256 ethInput
);

/**
* @notice Emitted when tokenToEth() swap transacted
*/
event TokenToEthSwap(
address swapper,
uint256 tokensInput,
uint256 ethOutput
);

/**
* @notice Emitted when liquidity provided to DEX and mints LPTs.
*/
event LiquidityProvided(
address liquidityProvider,
uint256 liquidityMinted,
uint256 ethInput,
uint256 tokensInput
);

/**
* @notice Emitted when liquidity removed from DEX and decreases LPT count within DEX.
*/
event LiquidityRemoved(
address liquidityRemover,
uint256 liquidityWithdrawn,
uint256 tokensOutput,
uint256 ethOutput
);

/* ========== CONSTRUCTOR ========== */

constructor(address tokenAddr) {
token = IERC20(tokenAddr); //specifies the token address that will hook into the interface and be used through the variable 'token'
}

/* ========== MUTATIVE FUNCTIONS ========== */

/**
* @notice initializes amount of tokens that will be transferred to the DEX itself from the erc20 contract mintee (and only them based on how Balloons.sol is written). Loads contract up with both ETH and Balloons.
* @param tokens amount to be transferred to 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) {}

/**
* @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) {}

/**
* @notice returns liquidity for a user.
* NOTE: this is not needed typically due to the `liquidity()` mapping variable being public and having a getter as a result. This is left though as it is used within the front end code (App.jsx).
* 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) {}

/**
* @notice sends Ether to DEX in exchange for $BAL
*/
function ethToToken() public payable returns (uint256 tokenOutput) {}

/**
* @notice sends $BAL tokens to DEX in exchange for Ether
*/
function tokenToEth(
uint256 tokenInput
) public returns (uint256 ethOutput) {}

/**
* @notice allows deposits of $BAL and $ETH to liquidity pool
* NOTE: parameter is the msg.value sent with this function call. That amount is used to determine the amount of $BAL needed as well and taken from the depositor.
* 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) {}

/**
* @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) {}
}
72 changes: 72 additions & 0 deletions extension/packages/hardhat/deploy/00_deploy_dex.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";
import { DEX } from "../typechain-types/contracts/DEX";
import { Balloons } from "../typechain-types/contracts/Balloons";

/**
* Deploys a contract named "YourContract" using the deployer account and
* constructor arguments set to the deployer address
*
* @param hre HardhatRuntimeEnvironment object.
*/
const deployYourContract: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
/*
On localhost, the deployer account is the one that comes with Hardhat, which is already funded.

When deploying to live networks (e.g `yarn deploy --network sepolia`), the deployer account
should have sufficient balance to pay for the gas fees for contract creation.

You can generate a random account with `yarn generate` which will fill DEPLOYER_PRIVATE_KEY
with a random private key in the .env file (then used on hardhat.config.ts)
You can run the `yarn account` command to check your balance in every network.
*/
const { deployer } = await hre.getNamedAccounts();
const { deploy } = hre.deployments;

await deploy("Balloons", {
from: deployer,
// Contract constructor arguments
//args: [deployer],
log: true,
// autoMine: can be passed to the deploy function to make the deployment process faster on local networks by
// automatically mining the contract deployment transaction. There is no effect on live networks.
autoMine: true,
});
// Get the deployed contract
// const yourContract = await hre.ethers.getContract("YourContract", deployer);
const balloons: Balloons = await hre.ethers.getContract("Balloons", deployer);
const balloonsAddress = await balloons.getAddress();

await deploy("DEX", {
from: deployer,
// Contract constructor arguments
args: [balloonsAddress],
log: true,
// autoMine: can be passed to the deploy function to make the deployment process faster on local networks by
// automatically mining the contract deployment transaction. There is no effect on live networks.
autoMine: true,
});

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);

// // 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,
// });
};

export default deployYourContract;

// Tags are useful if you have multiple deploy files and only want to run one of them.
// e.g. yarn deploy --tags YourContract
deployYourContract.tags = ["Balloons", "DEX"];
5 changes: 5 additions & 0 deletions extension/packages/hardhat/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"dependencies": {
"@openzeppelin/contracts": "^4.8.1"
}
}
Loading