Solidity Contract that allows anyone trustless pay fees for anyone
- Install truffle globally with
npm install -g truffle
- Install ganache-cli globally with
npm install -g ganache-cli
- Install local packages with
npm install
- Run ganache in separate terminal
scripts/rpc.sh
- Run tests with
npm test
On macOS you also need to install watchman: brew install watchman
- Inherit your smart contract from
Feeless
smaert contract - Add
feeless
modifier for any methods you wanna allow to call indirectly - Use
msgSender
instead ofmsg.sender
in these methods and methods internally called by them
For example token smart contract allowing to delegate transfers:
contract MyToken is StandardToken, Feeless {
string public constant symbol = "XXX";
string public constant name = "MyToken";
uint8 public constant decimals = 18;
string public constant version = "1.0";
function transfer(address _to, uint256 _value) public feeless returns (bool) {
balances[msgSender] = balances[msgSender].sub(_value);
balances[_to] = balances[_to].add(_value);
Transfer(msgSender, _to, _value);
return true;
}
}
Now you can delegate anyone to perform your (wallet1) transaction:
const target = myToken.options.address;
const nonce = await myToken.methods.nonces(wallet1).call();
const data = await myToken.methods.transfer(wallet2, 5 * 10**18).encodeABI();
const hash = web3.utils.sha3(target + data.substr(2) + web3.utils.toBN(nonce).toString(16,64));
const sig = await web3.eth.accounts.sign(hash, wallet1PrivateKey);
Now receiver (wallet2) is able to pay transaction fees for sender (wallet1):
await myToken.performFeelessTransaction(wallet1, target, data, nonce, sig).send({ from: wallet2 });
- Do not have replay-protection, delegated call can be performed in multiple chains (networks). To implement protection we need to introduce
block.chain_id
variable to EVM: ethereum/EIPs#901 - Wanna get rid of
msgSender
by adding something liketarget.authorizedcall(data, nonce, sig)
to EVM: ethereum/EIPs#1035