1

I am fairly new to smart contracts, and my team currently creating a game to collect entry fees of 0.01 ETH. Initially was going to let people transfer 0.01 ETH to our main wallet address, and have a background job to confirm the entry and wallet address, but I think smart contract would be a smarter option so we can prevent people from under/over sending, etc.

I would like to ask if it's a valid use case to create a smart contract to just force people to send x amount to a set wallet for game entry (for better UX), and if so how i could get started on making one that is hackproof.

If this isn't recommended/overcomplicating, please let me know as well. Thanks

1 Answer 1

0

A smart contract that allows people to send only 0.01 ETH to it is fairly simple to implement. Here is an example that allows people to directly send the ETH to it. It will revert if the user doesn't send exactly 0.01 ETH or if the user has already sent 0.01 ETH.

//SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;


error InvalidValueSent(uint value);
error AddressAlreadyEntered();

contract Fee {

    mapping(address => bool) public enteredMap;


    receive() external payable {
        if(msg.value != 0.01 ether) {
            revert InvalidValueSent(msg.value);
        } 
        if(enteredMap[msg.sender] == true) {
            revert AddressAlreadyEntered();
        }
        enteredMap[msg.sender] = true;
     }


}

After the user sends the correct amount of ETH, their address is marked as true in the enteredMap, which tracks which users have sent 0.01 ETH.

You can test it using this contract on remix:

contract Sender {

    error FailedToSend();
    
    function testSend(address payable addr) public payable {
        
        (bool sent, ) = addr.call{value: msg.value}("");
        if(!sent) {
            revert FailedToSend();
        }
    }
}

Additional function to send the contract's ETH balance to inputted addr:

function send(address addr) public {
        (bool sent, ) = addr.call{value: address(this).balance}("");
        if(!sent) {
            revert FailedToSend();
        }
     }

Alternative solution that sends the ETH to an address named wallet inside the receieve function:


    address public wallet = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;



    receive() external payable {
        if(msg.value != 0.01 ether) {
            revert InvalidValueSent(msg.value);
        } 
        if(enteredMap[msg.sender] == true) {
            revert AddressAlreadyEntered();
        }
        enteredMap[msg.sender] = true;
        (bool sent, ) = wallet.call{value: msg.value}("");
        if(!sent) {
            revert FailedToSend();
        }
     }
3
  • 1
    Awesome. With this smart contract, would the ETH go the contract address, or the initial deployer address? If the former (contract address), would we have to deploy different contracts to get the money out to a different prize pool wallet?
    – smbl
    Commented Dec 13, 2023 at 14:41
  • Currently the ETH would go the contract address, you can add a function that allows you to send ETH to whatever wallet address you'd like. I'll add a code snippet at the bottom that shows this using call. If you don't want to have to manually send the funds with an additional function, you could change the logic inside the receive function to send msg.value to your wallet.
    – Rohan Nero
    Commented Dec 14, 2023 at 17:33
  • @smbl Added a couple code snippets showing two different methods of handling the funds sent to the contract.
    – Rohan Nero
    Commented Dec 14, 2023 at 19:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.