Ethereum Gatling Gun — The Fastest Wallet Out There

  1. Send 1 Ether to some other wallet
  2. Send 1 ERC223 token to some other wallet
  3. Call a contract with no function arguments
  4. Call a contract with some function arguments as well as an Ether value

Introduction

One of the main issues blockchains are facing today is their lack of speed. Transactions on the Ethereum Mainnet can take minutes to mine, which is unacceptable for any application aspiring to be a true on-chain DApp (Decentralized Application).

Simple Proxy Contract

We can start off simple and write a smart contract that can forward a transaction onto the network in its own name. The address type in Solidity has a call function, which can be used to call one contract from another contract.

pragma solidity ^0.4.25;contract Proxy {
function execute(
address target, uint256 weiValue, bytes payload
) public {
target.call.value(weiValue)(payload);
}
}

Limitations of Solidity and Experimental Encoders

The obvious way to extend the Proxy contract to forward many transactions together would be to turn the arguments of the execute function into arrays and simply loop over them in the function like this:

pragma solidity ^0.4.25;contract ArrayProxy {
function execute(
address[] targets, uint256[] weiValues, bytes[] payloads
) public {
for(uint256 i = 0; i < targets.length; i++){
targets[i].call.value(weiValues[i])(payloads[i]);
}
}
}
Error: This type is only supported in the new experimental ABI encoder.
Use "pragma experimental ABIEncoderV2;" to enable the feature.
address[] targets, uint256[] weiValues, bytes[] payloads
^--------------^

Solidity != EVM, Leveraging Inline Assembly

While this may be a subjective feeling, it seems to me that the line between Solidity and the EVM (Ethereum Virtual Machine) is extremely blurred in the Blockchain community, to the point where “smart contracts” are almost synonymous with “Solidity”. Lets clearly disambiguate them.

Dissecting the CALL opcode

The first thing we need to realize is that we don’t necessarily need the explicit bytes[] type at all. What we actually need is to call another contract with some data, and the bytes[] type is just the way Solidity would have done it (if it could). But Solidity != EVM, so let’s see how the EVM performs internal transactions and what form it needs the payloads in.

assembly{
call(
<gas_limit>,
<target>,
<wei_value>,
<data_location>,
<data_length>,
<output_location>,
<output_length>
)
}

Writing the Gatling Gun wallet

So let’s stitch it all together. We shall create a fire function, which will have the following signature:

function fire(
bytes, address[] targets, uint256[] lengths, uint256[] values
)
require(targets.length == lengths.length);
require(targets.length == values.length);
uint256 payloadMemoryLocation;
assembly {
payloadMemoryLocation := mload(0x40)let payloadLengthLocation := add(4, calldataload(4))
let payloadLength := calldataload(payloadLengthLocation)
let payloadLocation := add(32, payloadLengthLocation)
calldatacopy(payloadMemoryLocation, payloadLocation, payloadLength)
mstore(0x40, add(payloadMemoryLocation, payloadLength))
}
uint256 offset = 0;
bool success;
for(uint256 i = 0; i < targets.length; i++){
address target = targets[i];
uint256 limit = lengths[i];
uint256 value = values[i];

# ASSEMBLY MAGIC HERE
require(success);
offset += limit;
}
assembly {
success := call(
gas,
target,
value,
add(payloadMemoryLocation, offset),
limit,
0,
0
)
}

Usage Demonstration

First thing we must do is get the Gatling Gun wallet onto the blockchain. To make this process easier, I wrote and deployed a Gatling Gun Deployment contract here (equivalent contract is also here on Ropsten if you want to play with it using testnet Ether) This contract allows anybody to get themselves their own Gatling Gun wallet by simply calling the deployGatlingGun(address owner) function of this contract, which creates a new one and sets the owner address to the one provided.

  1. Send 1 Ether to some other wallet
  2. Send 1 ERC223 token to some other wallet
  3. Call a contract with no function arguments
  4. Call a contract with some function arguments as well as an Ether value
0x785b8612b225b06764499f61e098725864ecd26b - 
1000000000000000000 -
0x
0x14c926f2290044b647e1bf2072e67b495eff1905 - 
0 -
0xa9059cbb000000000000000000000000abcd412dd0e1b3a3bf1131e927450f71f2e9085a0000000000000000000000000000000000000000000000000de0b6b3a7640000
0xeeb66b5624ddfa13bee72d9e9dc418a34a74b5c5 - 
0 -
0xd09de08a
0x06741096ef84fd751b0805a96583123b5cb11540 - 
1000000000000000000 -
0x8b3c99e3000000000000000000000000000000000000000000000000000000000000007b
0x785b8612b225b06764499f61e098725864ecd26b - 1000000000000000000 - 0x ; 0x14c926f2290044b647e1bf2072e67b495eff1905 - 0 - 0xa9059cbb000000000000000000000000abcd412dd0e1b3a3bf1131e927450f71f2e9085a0000000000000000000000000000000000000000000000000de0b6b3a7640000 ; 0xeeb66b5624ddfa13bee72d9e9dc418a34a74b5c5 - 0 - 0xd09de08a ; 0x06741096ef84fd751b0805a96583123b5cb11540 - 1000000000000000000 - 0x8b3c99e3000000000000000000000000000000000000000000000000000000000000007b

Evaluation

At this point you may naturally want to ask “What makes this better than sending the transactions out one by one?”. There are three main reasons.

Conclusion

This project and article are the result of my curiosity and desire to share interesting things with like-minded people out there. I hope you enjoyed the read. If this is something your project could make use of and you want to know more, check out the demonstration video on the ETH Gatling Gun homepage.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store