Skip to content

Add Support for AirdropOp for Bulk Distribution of Tokens #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 5, 2025

Conversation

zfedoran
Copy link
Contributor

@zfedoran zfedoran commented Jan 30, 2025

Problem
Distributing tokens to numerous accounts is inefficient with the current TransferOp, which limits to approximately 8 transfers per Solana transaction. Each transfer requires a separate signature, consuming 64 bytes of transaction message space, thereby increasing costs and reducing throughput.

Proposal
Introduce AirdropOp, a new opcode that allows a single source timelock account to distribute identical token amounts to multiple destination timelock accounts within a single transaction. This enhancement enables up to 255 recipients per airdrop, significantly improving efficiency and scalability.

Changes

  • Implemented AirdropOp struct and process_airdrop function to handle bulk token distribution.
  • Developed compact_airdrop_message and create_airdrop_message functions for message construction.
  • Added tests for multi-destination airdrops.

Usage
Use AirdropOp to efficiently distribute tokens from one source timelock to multiple destinations in a single transaction, reducing the number of required signatures and lowering transaction costs.

Compute Cost
An airdrop to 50 accounts consumes around 190,000 Compute Units (CU). Users should keep it under 55 to ensure the transaction doesn't fail. Larger airdrops are feasible though at increased costs by requesting more CU at the transaction level.

@zfedoran
Copy link
Contributor Author

Test run dropping 100 tokens into 50 virtual timelock accounts.

--------------------------------------------------------------------------------
sig:    5DhuPezEq8N6PEK61ffHGJFoeaukLQAzv2TQfLRbPng4hPXadCspsQKvASNiHQNqk64FhZ1HM3C7B9d18FG9RNLf
len:    455

body:
AQAABWl5pxthfbaftzuqU0Gl94b+r97l0GmEPiOHROc9Cj3lDcYoaKd+VYB6HNWIyaKadms+4q7NwH3gjP6RB91LMWVbzyLJDhTbBXOGSGB6c27r7Lfz5xSOp7Ac9VyX3EDOHLkuh3w+7s0+9PB9DbCB0vhxht+LaBmzM8ibWviozKel36m0clxUJB0cD/NcqGMTfR6BK7bRWfFONDRprCPnfMmu661KeW/MLhXcTGBhtF7Zs3Pyat/HmMp9LYzFgYJxjgEBCwACBAMBAQEBAQEB8wEIHjQAAAAAAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAvADAAMQAyADQAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBSQAAANMLTIV+n7SId+imOhsCv3w1YZHc0JUkkN1Sg9Dx/jImc7SCr19DnXmmaEXKAN55WvrcfSM5ZIvq0MS0iZMxoA9kAAAAAAAAADI=

ix:     ExecIx (8)
accounts:
        0: 86jQ7qWf8hnVM8FCcienfMqd7rpKQEDECUAij1bnbnmz
        2: 7BPHy2x5tiGBJDFmTJH2dCBhq5uM1Yq2JFeLwzhLdyYf
        4: G461Fxsna6p2H3PphwA8GPmDsuhVyfahq3K76ttNzjsv
        3: DTsaLZi9S9T4ojv4MgoxDEbrt9fFKQMozcivMYNZmnoe
        1: vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ
        1: vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ
        1: vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ
        1: vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ
        1: vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ
        1: vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ
        1: vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ

data:
        [8, 30, 52, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 16, 0, 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, 0, 24, 0, 25, 0, 26, 0, 27, 0, 28, 0, 29, 0, 30, 0, 31, 0, 32, 0, 33, 0, 34, 0, 35, 0, 36, 0, 37, 0, 38, 0, 39, 0, 40, 0, 41, 0, 42, 0, 43, 0, 44, 0, 45, 0, 46, 0, 47, 0, 48, 0, 49, 0, 50, 0, 52, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 73, 0, 0, 0, 211, 11, 76, 133, 126, 159, 180, 136, 119, 232, 166, 58, 27, 2, 191, 124, 53, 97, 145, 220, 208, 149, 36, 144, 221, 82, 131, 208, 241, 254, 50, 38, 115, 180, 130, 175, 95, 67, 157, 121, 166, 104, 69, 202, 0, 222, 121, 90, 250, 220, 125, 35, 57, 100, 139, 234, 208, 196, 180, 137, 147, 49, 160, 15, 100, 0, 0, 0, 0, 0, 0, 0, 50]


Length: 243 (0xf3) bytes
0000:   08 1e 34 00  00 00 00 00  00 00 01 00  02 00 03 00   ..4.............
0010:   04 00 05 00  06 00 07 00  08 00 09 00  0a 00 0b 00   ................
0020:   0c 00 0d 00  0e 00 0f 00  10 00 11 00  12 00 13 00   ................
0030:   14 00 15 00  16 00 17 00  18 00 19 00  1a 00 1b 00   ................
0040:   1c 00 1d 00  1e 00 1f 00  20 00 21 00  22 00 23 00   ........ .!.".#.
0050:   24 00 25 00  26 00 27 00  28 00 29 00  2a 00 2b 00   $.%.&.'.(.).*.+.
0060:   2c 00 2d 00  2e 00 2f 00  30 00 31 00  32 00 34 00   ,.-.../.0.1.2.4.
0070:   00 00 00 01  01 01 01 01  01 01 01 01  01 01 01 01   ................
0080:   01 01 01 01  01 01 01 01  01 01 01 01  01 01 01 01   ................
0090:   01 01 01 01  01 01 01 01  01 01 01 01  01 01 01 01   ................
00a0:   01 01 01 01  01 01 49 00  00 00 d3 0b  4c 85 7e 9f   ......I.....L.~.
00b0:   b4 88 77 e8  a6 3a 1b 02  bf 7c 35 61  91 dc d0 95   ..w..:...|5a....
00c0:   24 90 dd 52  83 d0 f1 fe  32 26 73 b4  82 af 5f 43   $..R....2&s..._C
00d0:   9d 79 a6 68  45 ca 00 de  79 5a fa dc  7d 23 39 64   .y.hE...yZ..}#9d
00e0:   8b ea d0 c4  b4 89 93 31  a0 0f 64 00  00 00 00 00   .......1..d.....
00f0:   00 00 32                                             ..2


cu:     185741
logs:
        "Program vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ invoke [1]"
        "Program vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ consumed 185741 of 200000 compute units"
        "Program vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ success"

@zfedoran
Copy link
Contributor Author

This instruction is compute limited, not transaction size limited.

One potential area for improvement would be to not use sig_verify and instead allow sending tokens from an external token account. This would add some overhead for the CPI but would allow for roughly 65 transfers in one transaction.

Initial tests for 65 transfers shows that this could be done. I suspect if we get more smart about PDA calculations, use no-std, etc... we could probably land closer to 75. This isn't a huge improvement at a cost of higher complexity but it is an option.

--------------------------------------------------------------------------------
sig:    3K75J3ut3SnnRHCpHV7Fx8G8S6WynDinm3TAEjCQ46tHjJLCbMk12N5RiNfLpMTZ7od3E5TuvT58dh7bz4bHdW4e
len:    500

body:
AQAABYn8IaSYw+LAe/YnjaUOtaNdGhGOlM/FUHmgqIjvXcsqDcYoaKd+VYB6HNWIyaKadms+4q7NwH3gjP6RB91LMWU+FXXDwP+3YcgUF56RJ/k7NONZKTgLnJcNpviN/HQf2ptKZ2vMrquWaxilDWf/Oocs4/v8M95K651Bf9CaVds4sCpbIGB2cWaOnll/33xYfSqoxJEHVj0gkKS42FDM0Fmu661KeW/MLhXcTGBhtF7Zs3Pyat/HmMp9LYzFgYJxjgEBCwACBAMBAQEBAQEBoAIIHkMAAAAAAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAvADAAMQAyADMANAA1ADYANwA4ADkAOgA7ADwAPQA+AD8AQABBAEMAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBSQAAADDrCPuN/bZqb/uDYmtm1d3ZNYSO4xPQHyBXp/jooXEUu/o4JCeQzMKNKDisdtC8kFmO1KzbzHg5Cpa0v5PIfglkAAAAAAAAAEE=

ix:     ExecIx (8)
accounts:
        0: AHdqmnAPf5jGhaGUpZQ99kwxUQhL4p8p9VYPSSDeipt9
        2: 5BMFtEi9Wn3LCLeMjt3LhCjMdLkvWjGXByoAiw3ut2Q9
        4: CrgDT2hriBqMCe7A4y8nTgJTTXjmUkYhP5iXvomGft4Y
        3: BTBznx4FJ8fwVyn4MASFJJngADxcfnzxDLMdyevEepoy
        1: vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ
        1: vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ
        1: vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ
        1: vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ
        1: vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ
        1: vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ
        1: vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ

data:
        [8, 30, 67, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 16, 0, 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, 0, 24, 0, 25, 0, 26, 0, 27, 0, 28, 0, 29, 0, 30, 0, 31, 0, 32, 0, 33, 0, 34, 0, 35, 0, 36, 0, 37, 0, 38, 0, 39, 0, 40, 0, 41, 0, 42, 0, 43, 0, 44, 0, 45, 0, 46, 0, 47, 0, 48, 0, 49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 54, 0, 55, 0, 56, 0, 57, 0, 58, 0, 59, 0, 60, 0, 61, 0, 62, 0, 63, 0, 64, 0, 65, 0, 67, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 73, 0, 0, 0, 48, 235, 8, 251, 141, 253, 182, 106, 111, 251, 131, 98, 107, 102, 213, 221, 217, 53, 132, 142, 227, 19, 208, 31, 32, 87, 167, 248, 232, 161, 113, 20, 187, 250, 56, 36, 39, 144, 204, 194, 141, 40, 56, 172, 118, 208, 188, 144, 89, 142, 212, 172, 219, 204, 120, 57, 10, 150, 180, 191, 147, 200, 126, 9, 100, 0, 0, 0, 0, 0, 0, 0, 65]


Length: 288 (0x120) bytes
0000:   08 1e 43 00  00 00 00 00  00 00 01 00  02 00 03 00   ..C.............
0010:   04 00 05 00  06 00 07 00  08 00 09 00  0a 00 0b 00   ................
0020:   0c 00 0d 00  0e 00 0f 00  10 00 11 00  12 00 13 00   ................
0030:   14 00 15 00  16 00 17 00  18 00 19 00  1a 00 1b 00   ................
0040:   1c 00 1d 00  1e 00 1f 00  20 00 21 00  22 00 23 00   ........ .!.".#.
0050:   24 00 25 00  26 00 27 00  28 00 29 00  2a 00 2b 00   $.%.&.'.(.).*.+.
0060:   2c 00 2d 00  2e 00 2f 00  30 00 31 00  32 00 33 00   ,.-.../.0.1.2.3.
0070:   34 00 35 00  36 00 37 00  38 00 39 00  3a 00 3b 00   4.5.6.7.8.9.:.;.
0080:   3c 00 3d 00  3e 00 3f 00  40 00 41 00  43 00 00 00   <.=.>[email protected]...
0090:   00 01 01 01  01 01 01 01  01 01 01 01  01 01 01 01   ................
00a0:   01 01 01 01  01 01 01 01  01 01 01 01  01 01 01 01   ................
00b0:   01 01 01 01  01 01 01 01  01 01 01 01  01 01 01 01   ................
00c0:   01 01 01 01  01 01 01 01  01 01 01 01  01 01 01 01   ................
00d0:   01 01 01 49  00 00 00 30  eb 08 fb 8d  fd b6 6a 6f   ...I...0......jo
00e0:   fb 83 62 6b  66 d5 dd d9  35 84 8e e3  13 d0 1f 20   ..bkf...5...... 
00f0:   57 a7 f8 e8  a1 71 14 bb  fa 38 24 27  90 cc c2 8d   W....q...8$'....
0100:   28 38 ac 76  d0 bc 90 59  8e d4 ac db  cc 78 39 0a   (8.v...Y.....x9.
0110:   96 b4 bf 93  c8 7e 09 64  00 00 00 00  00 00 00 41   .....~.d.......A


cu:     193303
logs:
        "Program vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ invoke [1]"
        "Program vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ consumed 193303 of 200000 compute units"
        "Program vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ success"

@zfedoran
Copy link
Contributor Author

When adding multiple of these instructions into a single transaction, the transaction limit is hit at a nice round 200 airdrops :)

Transfering 100 tokens to 200 accounts in one transaction:

sig:    3cUfNwvCounReziMGhwAAY3jYRaLDgayobUK2UXA5zhwBfsg4DEmGeRUthpxhzSYygXZ1hag7W85umCK268zG7cz

body:
AQAABbKgO798BdBA1kcqf6qDI8SnHLH34g62rqPz/0uqF9zXDcYoaKd+VYB6HNWIyaKadms+4q7NwH3gjP6RB91LMWWBANui9m8FYqo2gcrq6THTsTbNZbKlTejP+VnWI8cj7bEQSVhJQT5gpzKKbisHbREav3cPzuM71Cy3HRIt3ceM0oJ8vs6pBug+oddztXJJrggwUws0H7UayWXgG2fGTgiu661KeW/MLhXcTGBhtF7Zs3Pyat/HmMp9LYzFgYJxjgQBCwADBAIBAQEBAQEB8wEIHjQAAAAAAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAvADAAMQAyADQAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBSQAAALin2vodrP/KUKb5coVsaW7tA2hBLggeAar324sJFTGA0WG8ouZDhEPUef4yDgyBC5m/Z6GO3Dh8jsXxPU74uglkAAAAAAAAADIBCwADBAIBAQEBAQEB8wEIHjQAAAABAAAAMwA0ADUANgA3ADgAOQA6ADsAPAA9AD4APwBAAEEAQgBDAEQARQBGAEcASABJAEoASwBMAE0ATgBPAFAAUQBSAFMAVABVAFYAVwBYAFkAWgBbAFwAXQBeAF8AYABhAGIAYwBkADQAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBSQAAAAWuP+AtFjUHPOILfJ6x0Xtt5MmSjOoNxlgiglbRD9u8xgrBh7qVgEkZAZflLfVYIdv6VDpdQaSF/ehZqewAwwtkAAAAAAAAADIBCwADBAIBAQEBAQEB8wEIHjQAAAACAAAAZQBmAGcAaABpAGoAawBsAG0AbgBvAHAAcQByAHMAdAB1AHYAdwB4AHkAegB7AHwAfQB+AH8AgACBAIIAgwCEAIUAhgCHAIgAiQCKAIsAjACNAI4AjwCQAJEAkgCTAJQAlQCWADQAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBSQAAALJCflEBvljhKb2XueAnsXbLSTc9a7Y549aWMQDJIF5YDsc7DI5d4S48/CRRw4SdWoiJNvkynfXssi6Ha2gj4w1kAAAAAAAAADIBCwADBAIBAQEBAQEB8wEIHjQAAAADAAAAlwCYAJkAmgCbAJwAnQCeAJ8AoAChAKIAowCkAKUApgCnAKgAqQCqAKsArACtAK4ArwCwALEAsgCzALQAtQC2ALcAuAC5ALoAuwC8AL0AvgC/AMAAwQDCAMMAxADFAMYAxwDIADQAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBSQAAAKy2wKNAL/PcVT99JZ+v6I1k5EtmlM2buyr13T7gTwqj0aA7DaYZwpIrKOQX5jFJ3AIOhKO0tiqJKKbP2t6RuwJkAAAAAAAAADI=

tx len: 1229
tx cu:  713030
logs:
        "Program vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ invoke [1]"
        "Program vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ consumed 178250 of 800000 compute units"
        "Program vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ success"
        "Program vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ invoke [1]"
        "Program vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ consumed 178255 of 621750 compute units"
        "Program vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ success"
        "Program vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ invoke [1]"
        "Program vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ consumed 178258 of 443495 compute units"
        "Program vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ success"
        "Program vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ invoke [1]"
        "Program vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ consumed 178267 of 265237 compute units"
        "Program vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ success"

@zfedoran zfedoran merged commit c49f95d into main Feb 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant