sponsor logo

Cyfrin

Completed

TSender

TSender is a hyper gas efficient protocol for air dropping tokens to a large number of users. Inspired by the work of the Gaslite team.

Start Date May 24th, 2024 (12:00)
End Date May 31st, 2024 (12:00)
Time Left 0d/0h/0m
Rewards $15,000 USDC

TSender

gas-vs-1.png

Contest Details

Prize Pool

  • Total Prize Pool: $15,000

  • H/M - $12,500

  • Low - $1,375

  • Community judging: $1,125

  • Starts: May 24, 2024 Noon UTC

  • Ends: May 31, 2024 Noon UTC

Stats

  • nSLOC: 256
  • Complexity Scope: 284

Percent Gas Efficiency Improvement vs Solidity

gas-vs-1.png

About

Hyper gas efficient smart contracts for air dropping tokens to a large number of users. Inspired by the work of the Gaslite team. In the src folder, we have 4 main contracts:

  • TSender.sol: The Yul/Solidity implementation
  • TSender.huff: The Huff implementation
  • TSender_NoCheck.huff: The Huff implementation without the extra checks, making the output similar to GasliteDrop. Much more gas efficient, but without any safety rails.
  • TSenderReference.sol: The pure Solidity implementation

Each contract has 1 or 2 functions:

  • airdropERC20 (required): A function that takes in an array of recipients and an array of amounts, and sends the amounts to the recipients.
  • areValidLists (optional): A function that takes in an array of recipients and an array of amounts, and checks if the lists are valid.

TSender Features

  • Checks the totalAmount parameter matches the sum of the amounts array
  • Doesn't allow ETH to be sent with function calls
  • Makes sure the total lengths of the amounts array and recipients array are the same
  • Checks for zero address recipients

Additionally, we did not want to spend gas checking a few things, so we added a function called areListsValid that takes in a address[] recipients and uint256[] amounts to check for:

  • Duplicate addresses
  • Zero address sends
  • There is at least 1 recipient
  • All amounts are > 0
  • recipients.length == amounts.length

GasliteDrop Comparison

The work here was inspired by the Gaslite team with a few changes.

  1. The Yul & Huff have added safety checks (see TSender Features)
  2. The TSender_NoCheck.huff does not have the extra checks, but is just a gas optimized version of the original GasliteDrop contract.

Gas Comparisons

Note: Since our implementation adds more checks, the Huff code is slightly less gas efficient when working with additional recipients than the original gaslite codebase, but it is a safer smart contract. However, we did include a Huff contract the did not include those checks to show the power of using Huff to reduce gas costs.

Efficiency Improvement vs Solidity

# of recipientsYulGasliteHuffHuff (No Checks)
12.10%2.26%3.42%3.61%
103.23%3.38%3.51%3.65%
1003.48%3.62%3.52%3.66%
10003.51%3.66%3.53%3.66%

Actual Gas Costs

SolidityYulGasliteHuffHuff, no check
1 Recipient Drop5737756170560805540955300
10 Recipient Drops295287285737285296284931284507
100 Recipient Drops26746182581616257766525803602576786
1000 Recipient Drops2649054025561280255222292555552425520450

gas-vs-1000.png

Getting Started

Requirements

  • git
    • You'll know you did it right if you can run git --version and you see a response like git version x.x.x
  • foundry
    • You'll know you did it right if you can run forge --version and you see a response like forge 0.2.0 (816e00b 2023-03-16T00:05:26.396218Z)
  • huff
    • You'll know you did it right if you can run huffc --version and you see a response like huffc 0.3.2
  • halmos
    • You'll know you've done it right if you can run halmos --version and you see a response like Halmos 0.1.12

foundry-zksync

When we work with zksync, we plan to use foundry-zksync. You'll know you did it right if you can run forge --version and you see a response like forge 0.0.2 (816e00b 2023-03-16T00:05:26.396218Z). At the moment, it doesn't play nicely with Huff, so when we go to build with zksync, we remove all the Huff related code.

Installation

git clone https://github.com/cyfrin/2024-05-TSender
cd 2024-05-TSender
make

Quickstart / Usage

Testing

To test the codebase, you can run the following 2 commands:

make test
make halmos

Testing with zkSync

To test with zkSync, we must first remove our Huff tests. We will not be deploying the huff code to zkSync, and the codebases doesn't play nice with foundry-zksync.

To run zkSync tests:

  1. Comment out the following files
    1. TSenderHuffTest.t.sol
    2. TSenderHuffNoCheckTest.t.sol
    3. EquivalenceTest.sol
    4. DeployHuff.s.sol You'll need to leave this line uncommented in each file:
pragma solidity 0.8.24;
  1. Run the tests:
make zktest

or

forge test --zksync

We have an issue in foundry-zksync to fix the issue with avoid-contracts. That would be the ideal solution in the future.

Why no stateful fuzz tests?

Our contract is expected to never have state. There are no SSTORE opcodes in the bytecode of this contract.

Deployment

You'll need to uncomment out the DeployHuff.s.sol codebase. It's commented out because zkSync has a hard time compiling it at the moment. This is ok because we do not intend to deploy huff to zksync.

make deployYul
make deployHuff

Audit Data

Known issues

  • Does not work with fee-on-transfer tokens
  • Does not check the return value of ERC20s, but it does check to see if the transferFrom or transfer call was successful. Meaning ERC20s that return false on a failed transfer or transferFrom but successfully execute, are not supported. If any of the expected token integrations are vulnerable to this pattern, flag it.
  • Upgradable/Deny List tokens can prevent this contract from working. We expect that, in the case that this contract or any recipient is on a deny list, the entire transaction will revert.

Expected Token Integrations

  • USDC
  • USDT
  • LINK
  • WETH

Scope

#-- interfaces
|   #-- ITSender.sol
#-- protocol
|   #-- TSender.huff
|   #-- TSender.sol
|   #-- TSender_NoCheck.huff

Ignore:

#-- reference
    #-- TSenderReference.sol
#-- script/

Deploy scripts are not in scope because we can easily redeploy if we have an issue.

Chain compatibility

We expect to be able to run our deploy scripts, and it will prevent us from deploying contracts to chains that are not supported. Right now, zkSync will work with the yul based TSender.sol, and all other chains listed in the HelperConfig.sol will work with the TSender.huff contract.

Target deployment chains

  • TSender.sol:
    • zkSync Era
    • Everything in the TSender.huff list
  • TSender.huff:
    • Ethereum
    • Arbitrum
    • Optimism
    • Base
    • Blast

Notes

  • There is an issue with how quickly the foundry-zksync compiler works, so we avoid compiling the DeployHuff.s.sol contract.
  • Compliation takes a long time, so run tests accordingly. It may make sense to run tests with the standard foundry implementation before swapping to the foundry-zksync implementation.
  • Please take note of the target deployment chains during audit and check to see if our Huff or Solidity will work there.

Acknowledgements