You could implement some kind of meta-transaction system. Instead of signing directly a transaction, the employees sign a message containing the input parameters of the smart contract method, let's say inputA
, inputB
, and inputC
.
Basis
In the frontend ask the user for the inputs.
Hash the inputs plus a random parameter : web3.utils.soliditySha3(inputA, inputB, inputC, random);
. The random parameter prevents hash collisions if the same user signs twice the same data.
Ask the user to sign the hash with them private key.
You receive the signature, the user inputs, and the random parameter in your backend and inject them in the contract by signing the transaction with the application private key. The prototype of your solidity function should be something like this :
function myFunction(uint256 inputA, address inputB, uint256 inputC, uint256 random, address userAddress, bytes32 r,
bytes32 s, uint8 v) public;
Inside the function, hash the parameters and verify the user signature :
bytes32 hash = keccak256(abi.encodePacked(inputA, inputB, inputC, random));
require(ecrecover(hash, v, r, s) == userAddress);
Requirements to implement such logic
This kind of system has some requirements :
- That's the application which signs and sends the transaction in the backend on behalf of the user so you need to create an admin account and manage yourself the private key.
- You pay for the transactions so you need sufficient Ethers to cover the fees.
- You have to implement some kind of nonce management system to handle multiple concurrent requests.
Further remarks
Note that this system is poorly decentralized as the user does not sign directly the transaction. However, in the worst case, the application could only decide to not broadcast the transaction. There is no way to execute a malicious transaction as all input parameters are pre-signed by the user.