Skip to content
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

Feature Request: MultiOutput Edict for Airdrops #3658

Open
gamedevalice opened this issue Apr 22, 2024 · 4 comments
Open

Feature Request: MultiOutput Edict for Airdrops #3658

gamedevalice opened this issue Apr 22, 2024 · 4 comments

Comments

@gamedevalice
Copy link

gamedevalice commented Apr 22, 2024

This would make it a lot simpler to do large airdrops, and would require much fewer transactions, making it more cost efficient as well.

Based on:

pub struct Edict {
pub id: RuneId,
pub amount: u128,
pub output: u32,
}

I can see that the type of output is u32, i.e can have a maximum value of: 4,294,967,295

According to: https://bitcoinops.org/en/tools/calc-size/
You could probably fit roughly 100,000 outputs in a transaction that would be large enough to hit the block size limit.

So, given that the higher values are actually far from achievable, I suggest when output has a value of u32::MAX, we treat it as meaning:

  • send amount to every output (except the output to which the remaining change is sent to)

This approach requires no changes to the runestone's data structure or size, so it is 'free' as far as the runestone size fitting in a OP_RETURN is concerned.

@cryptoni9n
Copy link
Collaborator

I would like to second this request on behalf of many in the Ordicord. This has been the number one ask since halving by those wishing to airdrop their premined runes.

@gamedevalice
Copy link
Author

gamedevalice commented Apr 23, 2024

Note that according to this post from less than 2 hours ago this feature is already implemented in the protocol:
https://github.com/ordinals/ord/assets/124552025/e7fb05f5-ab70-4ced-8455-3c7014f747ad

To use it you set output to the total number of outputs (including OP_RETURNs). You also have the option to set amount to zero to split all of the runes in the transaction.

It seems like it may also airdrop to yourself. If that's the case, that's not ideal. You typically wouldn't want the airdrop to include the output where you are sending the remaining change,

Also note, even if this is considered sufficient, there are some remaining things to do:
1 - add it to the documentation so people can know about it
2 - adding a command to the wallet for constructing transactions with edicts and multiple outputs

For reference, the code to the current implementation is here:

if output == tx.output.len() {
// find non-OP_RETURN outputs
let destinations = tx
.output
.iter()
.enumerate()
.filter_map(|(output, tx_out)| {
(!tx_out.script_pubkey.is_op_return()).then_some(output)
})
.collect::<Vec<usize>>();
if !destinations.is_empty() {
if amount == 0 {
// if amount is zero, divide balance between eligible outputs
let amount = *balance / destinations.len() as u128;
let remainder = usize::try_from(*balance % destinations.len() as u128).unwrap();
for (i, output) in destinations.iter().enumerate() {
allocate(
balance,
if i < remainder { amount + 1 } else { amount },
*output,
);
}
} else {
// if amount is non-zero, distribute amount to eligible outputs
for output in destinations {
allocate(balance, amount.min(*balance), output);
}
}
}
} else {

@revofusion
Copy link
Contributor

revofusion commented Apr 23, 2024

@raphjaph the current split all works great already, what is needed rather is a flag for excluding an output # from the split all, so that we can reliably exclude change outputs

@gamedevalice
Copy link
Author

gamedevalice commented Apr 23, 2024

following the pattern that's already in place,
output == tx.output.len() means split to all outputs
so perhaps
output == tx.output.len() + 1 could mean split to all outputs except pointer

this allows the possibility for other kinds of special Edicts with new behaviors in the future, like:
output == tx.output.len() + 2
output == tx.output.len() + 3
etc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: To Do
Development

No branches or pull requests

4 participants