diff --git a/app/src/providers/PlayerProvider.tsx b/app/src/providers/PlayerProvider.tsx index 7f44202..824cce3 100644 --- a/app/src/providers/PlayerProvider.tsx +++ b/app/src/providers/PlayerProvider.tsx @@ -100,7 +100,7 @@ const PlayerProvider = ({ children }: { children: ReactNode }) => { abi, address: contractAddress, functionName: 'register', - value: parseEther("0.00005"), + value: parseEther("0.0005"), }) }, [writeContract]) diff --git a/src/Constants.sol b/src/Constants.sol index dca2613..82c37e3 100644 --- a/src/Constants.sol +++ b/src/Constants.sol @@ -5,4 +5,6 @@ contract Constants { //base addresses address public constant DAO_TOKEN = 0x11dC980faf34A1D082Ae8A6a883db3A950a3c6E8; address public constant POOL = 0x27004f6d0c1bB7979367D32Ba9d6DF6d61A18926; + address public constant WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public constant SWAP_ROUTER_02 = 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45; } diff --git a/src/RaidGeld.sol b/src/RaidGeld.sol index 67119c9..941597e 100644 --- a/src/RaidGeld.sol +++ b/src/RaidGeld.sol @@ -3,28 +3,39 @@ pragma solidity ^0.8.13; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; +import '@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol'; +import '@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol'; import {RaidGeldUtils} from "../src/RaidGeldUtils.sol"; import {Army, Player, Raider} from "../src/RaidGeldStructs.sol"; contract RaidGeld is ERC20, Ownable { + uint256 public constant MANTISSA = 1e4; - - uint256 public constant BUY_IN_AMOUNT = 0.00005 ether; + uint256 public constant BUY_IN_AMOUNT = 0.0005 ether; uint256 public immutable BUY_IN_DAO_TOKEN_AMOUNT; - uint256 public constant INITIAL_GELD = 50 * MANTISSA; - mapping(address => Player) private players; mapping(address => Army) private armies; + // WETH + IERC20 private constant weth = IERC20(Constants.WETH); + // RGCVII token ERC20 public daoToken; + // RGCVII pool address public pool; + // Uniswap + ISwapRouter02 private constant router = ISwapRouter02(Constants.SWAP_ROUTER_02); // Modifier for functions that should only be available to registered players modifier onlyPlayer() { require(players[msg.sender].created_at != 0, "Not an initiated player"); _; } + // Modifier for functions that should only be available to non initialized players + modifier newPlayer() { + require(players[msg.sender].created_at == 0, "Whoops, player already exists :)"); + _; + } constructor(address _daoToken, address _pool) ERC20("Raid Geld", "GELD") Ownable(msg.sender) { daoToken = ERC20(_daoToken); @@ -32,27 +43,14 @@ contract RaidGeld is ERC20, Ownable { BUY_IN_DAO_TOKEN_AMOUNT = 50 * 10 ** daoToken.decimals(); } - // This effectively registers the user - function register() external payable { - require(players[msg.sender].created_at == 0, "Whoops, player already exists :)"); - if (msg.value != 0) { - require(msg.value == BUY_IN_AMOUNT, "Incorrect buy in amount"); - } else { - //@notice this is not safe for arbitrary tokens, which may not follow the interface eg. USDT - //@notice but should be fine for the DAO token - require( - daoToken.transferFrom(msg.sender, address(this), BUY_IN_DAO_TOKEN_AMOUNT), - "Failed to transfer DAO tokens" - ); - } - + function init_player(address player) private { // Mint some starting tokens to the player - _mint(msg.sender, INITIAL_GELD); + _mint(player, INITIAL_GELD); // Set initial states - players[msg.sender] = + players[player] = Player({total_minted: INITIAL_GELD, created_at: block.timestamp, last_raided_at: block.timestamp}); - armies[msg.sender] = Army({ + armies[player] = Army({ moloch_denier: Raider({level: 0}), apprentice: Raider({level: 0}), anointed: Raider({level: 0}), @@ -61,6 +59,36 @@ contract RaidGeld is ERC20, Ownable { }); } + // New player want to register with ETH + function register_eth() external payable newPlayer { + require(weth.transferFrom(msg.sender, address(this), BUY_IN_AMOUNT), "Make sure to send exactly 0.0005 eth"); + weth.approve(address(router), amountIn); + ISwapRouter02.ExactInputSingleParams memory params = ISwapRouter02 + .ExactInputSingleParams({ + tokenIn: WETH, + tokenOut: DAI, + fee: 3000, + recipient: msg.sender, + amountIn: amountIn, + amountOutMinimum: amountOutMin, + sqrtPriceLimitX96: 0 + }); + router.exactInputSingle(params); + init_player(); + } + + // New player wants to register with dao + function register_dao() external payable newPlayer { + //@notice this is not safe for arbitrary tokens, which may not follow the interface eg. USDT + //@notice but should be fine for the DAO token + require( + daoToken.transferFrom(msg.sender, address(this), BUY_IN_DAO_TOKEN_AMOUNT), + "Failed to transfer DAO tokens" + ); + // Init player + init_player(msg.sender); + } + // Override for default number of decimals function decimals() public view virtual override returns (uint8) { return 4; diff --git a/test/RaidGeld.t.sol b/test/RaidGeld.t.sol index 2488f89..057b219 100644 --- a/test/RaidGeld.t.sol +++ b/test/RaidGeld.t.sol @@ -31,12 +31,12 @@ contract raid_geldTest is Test, Constants { } function registerPlayer() private { - raid_geld.register{value: raid_geld.BUY_IN_AMOUNT()}(); + raid_geld.register_eth{value: raid_geld.BUY_IN_AMOUNT()}(); } function registerPlayerWithDaoToken() private { raid_geld.daoToken().approve(address(raid_geld), raid_geld.BUY_IN_DAO_TOKEN_AMOUNT()); - raid_geld.register(); + raid_geld.register_dao(); } function test_00_no_fallback() public {