pragma solidity 0.8.20; //Do not change the solidity version as it negatively impacts submission grading // SPDX-License-Identifier: MIT import "@openzeppelin/contracts/access/Ownable.sol"; import "./YourToken.sol"; contract Vendor is Ownable { ///////////////// /// Errors ////// ///////////////// // Errors go here... error InvalidEthAmount(); error InsufficientVendorTokenBalance(uint256 available, uint256 required); error EthTransferFailed(address to, uint256 amount); error InvalidTokenAmount(); error InsufficientVendorEthBalance(uint256 available, uint256 required); ////////////////////// /// State Variables // ////////////////////// YourToken public immutable yourToken; uint256 public constant tokensPerEth = 100; //////////////// /// Events ///// //////////////// // Events go here... event BuyTokens(address indexed buyer, uint256 amountOfETH, uint256 amountOfTokens); event SellTokens(address indexed seller, uint256 amountOfTokens, uint256 amountOfETH); /////////////////// /// Constructor /// /////////////////// constructor(address tokenAddress) Ownable(msg.sender) { yourToken = YourToken(tokenAddress); } /////////////////// /// Functions ///// /////////////////// function buyTokens() external payable { if (msg.value == 0) revert InvalidEthAmount(); uint256 receivedToken = msg.value * tokensPerEth; uint256 availableToken = yourToken.balanceOf(address(this)); if (availableToken < receivedToken) revert InsufficientVendorTokenBalance(availableToken, receivedToken); yourToken.transfer(msg.sender, receivedToken); emit BuyTokens(msg.sender, msg.value, receivedToken); } function withdraw() public onlyOwner { address ownerAddr = payable(owner()); (bool sent,) = ownerAddr.call{value: address(this).balance}(""); if (!sent) revert EthTransferFailed(ownerAddr, address(this).balance); } function sellTokens(uint256 amount) public { if (amount == 0) revert InvalidTokenAmount(); yourToken.transferFrom(msg.sender, address(this), amount); uint256 receivedEth = amount / tokensPerEth; uint256 contractEth = address(this).balance; if (contractEth < receivedEth) revert InsufficientVendorEthBalance(contractEth, receivedEth); (bool sent,) = payable(msg.sender).call{value: receivedEth}(""); if (!sent) revert EthTransferFailed(msg.sender, receivedEth); emit SellTokens(msg.sender, amount, receivedEth); } }