Sign Up Smart Contract: Partial Solution and its Security Concerns
One was trying to create an app (as a side project), and one of its feature is creating a wallet for free (one call it "sign up"). If you'd created an account on read.cash, you know that it creates the wallet for you, asks you to save its key, and violà the wallet is yours! One is trying to imitate the same functionality in NEAR Protocol: creating a NEAR wallet for the user.
The thing is, a wallet in BCH, as far as one's concern, doesn't require fee for resources, like storage fee, which is required in NEAR Protocol. (Please correct me in the discussion below if one is wrong). NEAR wallet requires some NEAR during creation, with 0.05 Ⓝ reserved for transactions, and a minute amount for storage (less than 0.002 initially, but will increase as it stores more, perhaps via transaction, or access key if you login to other accounts using your wallet, or deploy a smart contract on your wallet, etc).
So, the account where the contract is deployed to, which we'll call it contract.near, will be responsible to pay for the wallet creation. Of course you can use another account, but that increases complexity. Just like 10% of a tip goes to read.cash (ignoring other cases), royalties charged will go to contract.near, which wallet creation fund will withdrawn from. Hence this assumes we have enough fund for the creation.
Then we'll use the linkdrop contract (there are many other code which you could google via "near linkdrop contract github") to create a link for the user to create an account. To sign a contract, some account needs to initiate a transaction.
Only an account can initiate a transaction. A user requesting to sign up doesn't have an account, so we require the contract to self-initiate. One haven't experimented with near call
directly on-chain, though one doubt it'll work without installing near-cli on-chain. Anyways, until the contract could self-initiate, someone needs to perform the initiation. Anyone can perform the initialization without paying for the deposit (though they need to pay for gas fee). The smart contract will attach a deposit upon receiving an initialization, then perform cross-contract calls to a linkdrop contract deployed elsewhere. When finish, the link to create a new account will be made available.
Meanwhile, the client will wait for the transaction to finish, we lock their screen (as a temporary measure) to prevent them from repeatedly (perhaps impatiently) clicking the sign up link. When finished, we will redirect the client to a new tab for wallet creation.
That's the workaround for now. In the future, one thought of a near ask
where the contract could near call
itself so it could sign the initial contract itself. Currently, although the contract could sign itself, the initial call needs to be initiated, which requires an outside call. An outside call means someone needs to hold the private key to sign the contract, hence it can't be done in the client's side, again for security reasons.
Next, let's look at some concerns with this approach.
Concerns from client side
Previously, we mentioned locking the client from repeatedly clicking the link. The repetition can cause re-entrancy attacks (or maybe other attacks that one don't know the name). Repeatedly clicking 100 times means 100 wallet creation, hence draining the funds for future wallet creation (you don't expect the funds to be unlimited, do you?)
Concerns from server side
And we have a server that sign the contract initially; hence the server is holding a private key. Until this is solved, it can't be decentralized. It's not trustless. Furthermore, the server is hosted somewhere else like Heroku or Microsoft Azure, so you still have to trust them to keep the private key safe. Another being hackers can hack into the server and retrieve the private key. Nothing is really safe here. That's why one wants a solution like near ask
, and one might experiment it in the future and write another article on it if one found a solution.
Concerns from funding side
You are funding the wallet, it still comes out of your fund. Someone whom suddenly got excited and launch a DDOS attack on your "sign up" button will drain your pool. I.e. a person keeps signing up and create numerous accounts, with or without reasons. In such case, you can ask for the person's phone number (not email) if they're required to sign up. If they don't (immediately sign in because they have an address already), then you don't need the phone number. The phone number ensures that one phone can only sign up once, and it's only used for that purpose.
But that's far from eliminating DDOS. One could still hold numerous phone numbers (like one could hold numerous emails) and this render the counteract useless. Another being if customer request deleting their account. When you delete account, make sure to delete everything for real, don't just archive (this statement is retrieved from Basecamp, one can't remember which book it is, but either Jason Fried or DHH mentioned it, and it's practiced by Basecamp too). So if we delete, we still delete the phone number, and they could re-create them, and we don't know if we helped the same phone number create twice or not. Of course we could say we'll delete the data only after 14 days or something, and they can't spam, though they still can do the same thing repeated every 14 days and the system won't notice.
Also, since the contract is deployed public, we need to restrict who can call the contract. Usually, a linkdrop have someone pays for, and we don't want any random people to sign the contract, and we want to restrict to a list of account that can call the method. Here are two new concerns:
If we restrict to only the contract can call itself, the server which initiate the contract can steal the funds. It has a full-access key, anyways. This is unsafe.
If a random account save the private key, we don't worry about the above problem. Though, we need a method to constantly deposit some NEAR to that account, enough to cover GAS cost; otherwise it would run out of NEAR to pay GAS before you realize.
Conclusion
The idea is good, though there are lots more concerns. Perhaps it won't end up in mainnet, only in testnet. It might end up someone can create an account but without wallet, though one like the idea of linking wallet rather than linking account for signing up and signing in. Until the concerns are solved, this idea won't be deployed.
Remember to Like and Subscribe if you like my posts.
It's good for problem solving