0

I am working on a dApp that grabs json info based on the logged in metamask user. That info is passed on to my contract to allow the mint function to execute based on the value.

So for example if the info value is 30, that gets sent to the mint function and based on the number 30, it executes the mint function a certain way. -

function mint(uint256 amount, uint256 variable) public payable { }

My question is about security. How can I prevent people from using their own dApps or such, to execute my mint function with their own variable?

The problem is that the variable is important and needed so I do not want others to somehow pass their own variables to the mint function. I understand they can mint directly from etherscan but without my dApp the variable would basically be null and they wouldn't be able to mint without it.

How can I protect my smart contract function from being used by any other dApps or js projects other than my own? I want other people to be able to mint on my dApp so using my private keys doesn't seem like the right choice. Possibly like checking the url for the call inside the smart contract?

EDIT: To clarify further - I am looking for a way that my contract can check where the function call came from. If it didnt come from my site then it should fail. I am thinking something like cryptography/signing? Similar to off chain whitelists? Is it possible to use hashing or encryption sent from the dApp to the smart contract that controls access to the function thus removing the ability to use the function directly from etherscan?

example in theory -

 struct verifyOrigin {
  bytes32 r;
  bytes32 s;
  uint8 v;
 }
 enum verifyType {
  Sig
}

 bytes32 digest = keccak256(
      abi.encode(verifyType.Verified, msg.sender)
    );
  
    require(
      _isVerified(digest, verifyOrigin), 
     'Invalid'
    ); 

3 Answers 3

0

If you declare your function as public then anyone can your mint function. if you want to prevent from the other user then you use the modifier in your function.

try this :

address owner ;
mapping(address=>bool) private _mintable;
constructor(){
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function allowUser(address _user) public onlyOwner{
    _mintable[_user] = true;
}
function mint(uint256 amount, uint256 variable) public payable { 
     require(_mintable[msg.sender] == true , "You aren't allow to mint.");
}
4
  • Wouldn't that make the function only mintable by me? I would want others to be able to mint. Just need to verify it came from my website.
    – 730wavy
    Feb 21, 2022 at 20:43
  • Check the edited answer. Feb 22, 2022 at 4:50
  • Hi Im not sure I understand your method. Does this mean I'd have to add each user based like a whitelist?
    – 730wavy
    Feb 23, 2022 at 4:22
  • Yes. If you want to make your function public and limited user then only whitelist is best option. Feb 25, 2022 at 5:22
0

OpenZeppelin has excellent functionality for this: https://docs.openzeppelin.com/contracts/4.x/access-control#role-based-access-control

Role based access controls allow you to define roles, eg. regular users, supervisors, or managers etc.

bytes32 public constant BASIC_ROLE = keccak256("BASIC_ROLE");
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");

You can then define functions that are only available to certain roles:

function mint(address to, uint256 amount) public onlyRole(ADMIN_ROLE) {
    _mint(to, amount);
}

Alternatively, you could use require statements or if conditions within the function to change the behaviour depending on the group the user belongs too.

Granting and revoking roles is as easy as:

grantRole(BASIC_ROLE, msg.sender);
renounceRole(BASIC_ROLE, msg.sender);
0

I don't get it one thing: Will you pay the mint gas fees in your dApp? We can ask the same question like: Will you run the transaction or do users run their own transaction?

If you'll not pay the gas fees then you are right. You can use signatures. Add one more parameter to your mint function named verifySignature and if it is not 0, then write your things. If it is zero, that transaction was not sent by your dApp. Of course, there can be fake signatures. Because of this, you need the check out the signature address.

If you'll pay the gas fees, then you can use msg.sender is a security parameter.

3
  • Interesting. I actually ended up trying to use merkle tree to verify the correct parameters are set. This only works though by me creating a list of the IDs I want sent. I have to look into your suggestion more. It would be that the user pays gas though.
    – 730wavy
    Mar 4, 2022 at 5:46
  • Okay. Let me know if there will be some progress. Mar 4, 2022 at 10:39
  • Thanks. I think I'm close to finalizing my solution. I actually have a bounty on a question in regards to it.
    – 730wavy
    Mar 4, 2022 at 13:45

Your Answer

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

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