From cde9130bba9426981c829f600656e70cc42b1429 Mon Sep 17 00:00:00 2001 From: albttx Date: Fri, 4 Oct 2024 12:08:57 +0100 Subject: [PATCH 01/17] chore: foo20-airdrop --- .../demo/airdrop/grc20_merkle_airdrop/gno.mod | 1 + .../grc20_merkle_airdrop.gno | 96 ++++++++++++++++ .../grc20_merkle_airdrop_test.gno | 105 ++++++++++++++++++ .../gno.land/r/demo/foo20-airdrop/airdrop.gno | 44 ++++++++ .../r/demo/foo20-airdrop/airdrop_test.gno | 79 +++++++++++++ .../gno.land/r/demo/foo20-airdrop/gno.mod | 1 + 6 files changed, 326 insertions(+) create mode 100644 examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/gno.mod create mode 100644 examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno create mode 100644 examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno create mode 100644 examples/gno.land/r/demo/foo20-airdrop/airdrop.gno create mode 100644 examples/gno.land/r/demo/foo20-airdrop/airdrop_test.gno create mode 100644 examples/gno.land/r/demo/foo20-airdrop/gno.mod diff --git a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/gno.mod b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/gno.mod new file mode 100644 index 00000000000..66e90798ad1 --- /dev/null +++ b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/gno.mod @@ -0,0 +1 @@ +module gno.land/p/demo/airdrop/grc20_merkle_airdrop diff --git a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno new file mode 100644 index 00000000000..6ed914184b1 --- /dev/null +++ b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno @@ -0,0 +1,96 @@ +package grc20_merkle_airdrop + +import ( + "crypto/sha256" + "encoding/hex" + "errors" + "fmt" + "std" + + "gno.land/p/demo/avl" + "gno.land/p/demo/grc/grc20" + "gno.land/p/demo/merkle" + "gno.land/r/demo/foo20" + "gno.land/r/demo/users" +) + +var ( + ErrAlreadyClaimed = errors.New("already claimed") + ErrInvalidProof = errors.New("invalid merkle proof") +) + +type AirdropData struct { + Address std.Address + // TODO: use std.Coin + Amount uint64 + // Amount std.Coin +} + +func (data AirdropData) Bytes() []byte { + // TODO: use binary.Write + // var buf bytes.Buffer + // binary.Write(&buf, binary.BigEndian, d) + // return buf.Bytes() + // OR: use json.Marshal for frontend compatibilities + + s := fmt.Sprintf("%v", data) + return []byte(s) +} + +type MerkleAirdrop struct { + root string + + token grc20.Token + claimed *avl.Tree +} + +func NewMerkleAirdrop(merkleroot string, token grc20.Token) *MerkleAirdrop { + return &MerkleAirdrop{ + root: merkleroot, + + token: token, + claimed: avl.NewTree(), + } +} + +func (ma *MerkleAirdrop) Root() string { + return ma.root +} + +func (ma *MerkleAirdrop) Claim(data AirdropData, proofs []merkle.Node) error { + shasum := sha256.Sum256(data.Bytes()) + hash := hex.EncodeToString(shasum[:]) + + if ma.claimed.Has(hash) { + return ErrAlreadyClaimed + } + + if !merkle.Verify(ma.root, data, proofs) { + return ErrInvalidProof + } + + // THIS WORKS + // foo20.Transfer(users.AddressOrName(data.Address), data.Amount) + + // THIS DOES NOT WORK + // foo20.GRC20().Transfer(data.Address, data.Amount) + + err := ma.token.Transfer(data.Address, data.Amount) + if err != nil { + return err + } + + ma.claimed.Set(hash, data.Amount) + return nil +} + +func (ma MerkleAirdrop) TotalClaimed() uint64 { + var claimed uint64 = 0 + + ma.claimed.Iterate("", "", func(k string, v interface{}) bool { + claimed += v.(uint64) + return false + }) + + return claimed +} diff --git a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno new file mode 100644 index 00000000000..033f5ec5a6c --- /dev/null +++ b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno @@ -0,0 +1,105 @@ +package grc20_merkle_airdrop + +import ( + "std" + "testing" + + "gno.land/p/demo/airdrop/grc20_merkle_airdrop" + "gno.land/p/demo/grc/grc20" + "gno.land/p/demo/merkle" + "gno.land/p/demo/urequire" + "gno.land/r/demo/foo20" + "gno.land/r/demo/users" +) + +func getLeaves() []merkle.Hashable { + var leaves = []AirdropData{ + { + Address: "g1sw5xklxjjuv0yvuxy5f5s3l3mnj0nqq626a9wr", // albttx.gno + Amount: 10000, + }, + { + Address: "g1zyvskpxg5lv4qpygtuvp93zprrrjpk2exa9rfx", + Amount: 10000, + }, + { + Address: "g14szvkruznx49sxe4m9dmg3m8606sm6yp4a0wv8", + Amount: 10000, + }, + } + + resp := make([]merkle.Hashable, len(leaves)) + for i, leave := range leaves { + resp[i] = leave + } + return resp +} + +func TestRegisterMerkle(t *testing.T) { + leaves := getLeaves() + tree := merkle.NewTree(leaves) + root := tree.Root() + contractAddr := std.DerivePkgAddr("gno.land/r/demo/tok20-airdrop") + + token := grc20.NewBanker("TOKEN", "TOK", 6) + token.Mint(contractAddr, 50000) // Airdrop contract + + tok20airdrop := NewMerkleAirdrop(root, token.Token()) + _ = tok20airdrop +} + +func TestClaimAirdrop(t *testing.T) { + contractAddr := std.DerivePkgAddr("gno.land/r/demo/tok20-airdrop") + std.TestSetOrigCaller(contractAddr) + + leaves := getLeaves() + tree := merkle.NewTree(leaves) + root := tree.Root() + + // instantiate foo20 airdrop contract + token := grc20.NewBanker("TOKEN", "TOK", 6) + token.Mint(contractAddr, 50000) // Airdrop contract + + tok20airdrop := NewMerkleAirdrop(root, token.Token()) + + sumClaimed := uint64(0) + for _, leaf := range leaves { + data := leaf.(AirdropData) + println(data) + + sumClaimed += data.Amount + + proofs, err := tree.Proof(leaf) + urequire.NoError(t, err) + + // claim airdrop + err = tok20airdrop.Claim(data, proofs) + urequire.NoError(t, err) + } + + ttClaimed := tok20airdrop.TotalClaimed() + urequire.Equal(t, ttClaimed, sumClaimed) +} + +func TestDoubleClaim(t *testing.T) { + leaves := getLeaves() + + contractAddr := std.DerivePkgAddr("gno.land/r/demo/tok20-airdrop") + std.TestSetOrigCaller(contractAddr) + + tree := merkle.NewTree(leaves) + token := grc20.NewBanker("TOKEN", "TOK", 6) + token.Mint(contractAddr, 50000) + + tok20airdrop := NewMerkleAirdrop(tree.Root(), token.Token()) + + leaf := leaves[0] + proofs, err := tree.Proof(leaf) + urequire.NoError(t, err) + + err = tok20airdrop.Claim(leaf.(AirdropData), proofs) + urequire.NoError(t, err) + + err = tok20airdrop.Claim(leaf.(AirdropData), proofs) + urequire.Error(t, err, ErrAlreadyClaimed.Error()) +} diff --git a/examples/gno.land/r/demo/foo20-airdrop/airdrop.gno b/examples/gno.land/r/demo/foo20-airdrop/airdrop.gno new file mode 100644 index 00000000000..53af8df0dbc --- /dev/null +++ b/examples/gno.land/r/demo/foo20-airdrop/airdrop.gno @@ -0,0 +1,44 @@ +package foo20airdrop + +import ( + "std" + + "gno.land/p/demo/airdrop/grc20_merkle_airdrop" + "gno.land/p/demo/grc/grc20" + "gno.land/p/demo/merkle" + "gno.land/r/demo/foo20" +) + +var ( + token grc20.Token + + // admin std.Address = "g1sw5xklxjjuv0yvuxy5f5s3l3mnj0nqq626a9wr" // albttx.gno + + foo20airdrop *grc20_merkle_airdrop.MerkleAirdrop +) + +func RegisterMerkleRoot(root string) { + token = foo20.Token() + foo20airdrop = nil + + if foo20airdrop != nil { + panic("foo20 airdrop merkle root is already registered") + } + foo20airdrop = grc20_merkle_airdrop.NewMerkleAirdrop(root, token) +} + +func Claim(data grc20_merkle_airdrop.AirdropData, proofs []merkle.Node) { + err := foo20airdrop.Claim(data, proofs) + if err != nil { + panic(err.Error()) + } + + // err = token.Transfer(data.Address, data.Amount) + // if err != nil { + // panic(err.Error()) + // } +} + +func TotalClaimed() uint64 { + return foo20airdrop.TotalClaimed() +} diff --git a/examples/gno.land/r/demo/foo20-airdrop/airdrop_test.gno b/examples/gno.land/r/demo/foo20-airdrop/airdrop_test.gno new file mode 100644 index 00000000000..b80ad269988 --- /dev/null +++ b/examples/gno.land/r/demo/foo20-airdrop/airdrop_test.gno @@ -0,0 +1,79 @@ +package foo20airdrop + +import ( + "std" + "testing" + + "gno.land/p/demo/airdrop/grc20_merkle_airdrop" + "gno.land/p/demo/merkle" + "gno.land/p/demo/urequire" + "gno.land/p/demo/users" + "gno.land/r/demo/foo20" +) + +func getLeaves() []merkle.Hashable { + var leaves = []grc20_merkle_airdrop.AirdropData{ + { + Address: "g1sw5xklxjjuv0yvuxy5f5s3l3mnj0nqq626a9wr", // albttx.gno + Amount: 10000, + }, + { + Address: "g1zyvskpxg5lv4qpygtuvp93zprrrjpk2exa9rfx", + Amount: 10000, + }, + { + Address: "g14szvkruznx49sxe4m9dmg3m8606sm6yp4a0wv8", + Amount: 10000, + }, + } + + resp := make([]merkle.Hashable, len(leaves)) + for i, leave := range leaves { + resp[i] = leave + } + return resp +} + +func TestRegisterMerkle(t *testing.T) { + leaves := getLeaves() + + tree := merkle.NewTree(leaves) + root := tree.Root() + + RegisterMerkleRoot(root) +} + +func TestClaimAirdrop(t *testing.T) { + leaves := getLeaves() + + contractAddr := std.DerivePkgAddr("gno.land/r/demo/foo20-airdrop") + std.TestSetOrigCaller(contractAddr) + + for _, leave := range leaves { + // Get 10k token + foo20.Faucet() + } + + // instantiate foo20 airdrop contract + tree := merkle.NewTree(leaves) + RegisterMerkleRoot(tree.Root()) + + sumClaimed := uint64(0) + for _, leaf := range leaves { + data := leaf.(grc20_merkle_airdrop.AirdropData) + user := data.Address + sumClaimed += data.Amount + + proofs, err := tree.Proof(leaf) + urequire.NoError(t, err) + + // claim airdrop + Claim(data, proofs) + + balance := foo20.BalanceOf(users.AddressOrName(data.Address)) + urequire.Equal(t, balance, uint64(10000)) + } + + ttClaimed := TotalClaimed() + urequire.Equal(t, ttClaimed, sumClaimed) +} diff --git a/examples/gno.land/r/demo/foo20-airdrop/gno.mod b/examples/gno.land/r/demo/foo20-airdrop/gno.mod new file mode 100644 index 00000000000..d1e3892da23 --- /dev/null +++ b/examples/gno.land/r/demo/foo20-airdrop/gno.mod @@ -0,0 +1 @@ +module gno.land/r/demo/foo20-airdrop From 4d5f758ce45a6c51d89acb98e38938337f934da6 Mon Sep 17 00:00:00 2001 From: albttx Date: Fri, 4 Oct 2024 12:11:50 +0100 Subject: [PATCH 02/17] chore: fmt --- .../airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno index 6ed914184b1..dffd45c43be 100644 --- a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno +++ b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno @@ -4,12 +4,12 @@ import ( "crypto/sha256" "encoding/hex" "errors" - "fmt" "std" "gno.land/p/demo/avl" "gno.land/p/demo/grc/grc20" "gno.land/p/demo/merkle" + "gno.land/p/demo/ufmt" "gno.land/r/demo/foo20" "gno.land/r/demo/users" ) @@ -33,7 +33,7 @@ func (data AirdropData) Bytes() []byte { // return buf.Bytes() // OR: use json.Marshal for frontend compatibilities - s := fmt.Sprintf("%v", data) + s := ufmt.Sprintf("%v", data) return []byte(s) } From 0d378ac9905c8595e98e65df8103762e598e026a Mon Sep 17 00:00:00 2001 From: albttx Date: Fri, 4 Oct 2024 12:18:03 +0100 Subject: [PATCH 03/17] fix: transpile --- .../demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno | 2 -- examples/gno.land/r/demo/foo20-airdrop/airdrop.gno | 2 -- 2 files changed, 4 deletions(-) diff --git a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno index dffd45c43be..e8459b10e82 100644 --- a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno +++ b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno @@ -10,8 +10,6 @@ import ( "gno.land/p/demo/grc/grc20" "gno.land/p/demo/merkle" "gno.land/p/demo/ufmt" - "gno.land/r/demo/foo20" - "gno.land/r/demo/users" ) var ( diff --git a/examples/gno.land/r/demo/foo20-airdrop/airdrop.gno b/examples/gno.land/r/demo/foo20-airdrop/airdrop.gno index 53af8df0dbc..46cfcc1c483 100644 --- a/examples/gno.land/r/demo/foo20-airdrop/airdrop.gno +++ b/examples/gno.land/r/demo/foo20-airdrop/airdrop.gno @@ -1,8 +1,6 @@ package foo20airdrop import ( - "std" - "gno.land/p/demo/airdrop/grc20_merkle_airdrop" "gno.land/p/demo/grc/grc20" "gno.land/p/demo/merkle" From 5e69b3b47607fe071906919177e38c40d1fb94b5 Mon Sep 17 00:00:00 2001 From: albttx Date: Fri, 4 Oct 2024 12:41:53 +0100 Subject: [PATCH 04/17] chore: fmt --- .../airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno index 033f5ec5a6c..a769e1c946c 100644 --- a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno +++ b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno @@ -4,12 +4,9 @@ import ( "std" "testing" - "gno.land/p/demo/airdrop/grc20_merkle_airdrop" "gno.land/p/demo/grc/grc20" "gno.land/p/demo/merkle" "gno.land/p/demo/urequire" - "gno.land/r/demo/foo20" - "gno.land/r/demo/users" ) func getLeaves() []merkle.Hashable { From 5ff3cb3c10110ff961d5ce8fe21771a2c8877d1a Mon Sep 17 00:00:00 2001 From: albttx Date: Fri, 4 Oct 2024 14:28:26 +0100 Subject: [PATCH 05/17] chore: generic AirdropData --- examples/gno.land/p/demo/airdrop/airdrop.gno | 43 ++++++++++++++++ .../grc20_merkle_airdrop.gno | 27 ++-------- .../grc20_merkle_airdrop_test.gno | 49 +++++++++---------- .../gno.land/r/demo/foo20-airdrop/airdrop.gno | 8 +-- .../r/demo/foo20-airdrop/airdrop_test.gno | 46 +++++++---------- 5 files changed, 91 insertions(+), 82 deletions(-) create mode 100644 examples/gno.land/p/demo/airdrop/airdrop.gno diff --git a/examples/gno.land/p/demo/airdrop/airdrop.gno b/examples/gno.land/p/demo/airdrop/airdrop.gno new file mode 100644 index 00000000000..226dffe06de --- /dev/null +++ b/examples/gno.land/p/demo/airdrop/airdrop.gno @@ -0,0 +1,43 @@ +package airdrop + +import ( + "encoding/json" + "std" +) + +type AirdropData interface { + Bytes() []byte + Address() std.Address + Amount() uint64 +} + +// Data is complient with AirdropData interface +type Data struct { + data struct { + Address std.Address `json:"address"` + Amount uint64 `json:"amount"` + } +} + +func NewData(addr std.Address, amount uint64) Data { + d := Data{} + d.data.Address = addr + d.data.Amount = amount + return d +} + +func (d Data) Bytes() []byte { + out, err := json.Marshal(d.data) + if err != nil { + panic(err) + } + return []byte(out) +} + +func (d Data) Address() std.Address { + return d.data.Address +} + +func (d Data) Amount() uint64 { + return d.data.Amount +} diff --git a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno index e8459b10e82..3618bc39942 100644 --- a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno +++ b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno @@ -3,13 +3,14 @@ package grc20_merkle_airdrop import ( "crypto/sha256" "encoding/hex" + "encoding/json" "errors" "std" + "gno.land/p/demo/airdrop" "gno.land/p/demo/avl" "gno.land/p/demo/grc/grc20" "gno.land/p/demo/merkle" - "gno.land/p/demo/ufmt" ) var ( @@ -17,24 +18,6 @@ var ( ErrInvalidProof = errors.New("invalid merkle proof") ) -type AirdropData struct { - Address std.Address - // TODO: use std.Coin - Amount uint64 - // Amount std.Coin -} - -func (data AirdropData) Bytes() []byte { - // TODO: use binary.Write - // var buf bytes.Buffer - // binary.Write(&buf, binary.BigEndian, d) - // return buf.Bytes() - // OR: use json.Marshal for frontend compatibilities - - s := ufmt.Sprintf("%v", data) - return []byte(s) -} - type MerkleAirdrop struct { root string @@ -55,7 +38,7 @@ func (ma *MerkleAirdrop) Root() string { return ma.root } -func (ma *MerkleAirdrop) Claim(data AirdropData, proofs []merkle.Node) error { +func (ma *MerkleAirdrop) Claim(data airdrop.AirdropData, proofs []merkle.Node) error { shasum := sha256.Sum256(data.Bytes()) hash := hex.EncodeToString(shasum[:]) @@ -73,12 +56,12 @@ func (ma *MerkleAirdrop) Claim(data AirdropData, proofs []merkle.Node) error { // THIS DOES NOT WORK // foo20.GRC20().Transfer(data.Address, data.Amount) - err := ma.token.Transfer(data.Address, data.Amount) + err := ma.token.Transfer(data.Address(), data.Amount()) if err != nil { return err } - ma.claimed.Set(hash, data.Amount) + ma.claimed.Set(hash, data.Amount()) return nil } diff --git a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno index a769e1c946c..0dd2d7cbf9b 100644 --- a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno +++ b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno @@ -4,36 +4,29 @@ import ( "std" "testing" + "gno.land/p/demo/airdrop" "gno.land/p/demo/grc/grc20" "gno.land/p/demo/merkle" + "gno.land/p/demo/ufmt" "gno.land/p/demo/urequire" + "gno.land/p/demo/users" ) -func getLeaves() []merkle.Hashable { - var leaves = []AirdropData{ - { - Address: "g1sw5xklxjjuv0yvuxy5f5s3l3mnj0nqq626a9wr", // albttx.gno - Amount: 10000, - }, - { - Address: "g1zyvskpxg5lv4qpygtuvp93zprrrjpk2exa9rfx", - Amount: 10000, - }, - { - Address: "g14szvkruznx49sxe4m9dmg3m8606sm6yp4a0wv8", - Amount: 10000, - }, - } +func getLeaves(size int) []merkle.Hashable { + leaves := make([]merkle.Hashable, size) - resp := make([]merkle.Hashable, len(leaves)) - for i, leave := range leaves { - resp[i] = leave + for i := 0; i < size; i++ { + leaves[i] = airdrop.NewData( + std.DerivePkgAddr(ufmt.Sprintf("gno.land/test/%d", i)), + 10000, + ) } - return resp + + return leaves } func TestRegisterMerkle(t *testing.T) { - leaves := getLeaves() + leaves := getLeaves(3) tree := merkle.NewTree(leaves) root := tree.Root() contractAddr := std.DerivePkgAddr("gno.land/r/demo/tok20-airdrop") @@ -49,7 +42,7 @@ func TestClaimAirdrop(t *testing.T) { contractAddr := std.DerivePkgAddr("gno.land/r/demo/tok20-airdrop") std.TestSetOrigCaller(contractAddr) - leaves := getLeaves() + leaves := getLeaves(5) tree := merkle.NewTree(leaves) root := tree.Root() @@ -61,10 +54,9 @@ func TestClaimAirdrop(t *testing.T) { sumClaimed := uint64(0) for _, leaf := range leaves { - data := leaf.(AirdropData) - println(data) + data := leaf.(airdrop.Data) - sumClaimed += data.Amount + sumClaimed += data.Amount() proofs, err := tree.Proof(leaf) urequire.NoError(t, err) @@ -72,6 +64,9 @@ func TestClaimAirdrop(t *testing.T) { // claim airdrop err = tok20airdrop.Claim(data, proofs) urequire.NoError(t, err) + + balance := token.BalanceOf(data.Address()) + urequire.Equal(t, balance, uint64(10000)) } ttClaimed := tok20airdrop.TotalClaimed() @@ -79,7 +74,7 @@ func TestClaimAirdrop(t *testing.T) { } func TestDoubleClaim(t *testing.T) { - leaves := getLeaves() + leaves := getLeaves(5) contractAddr := std.DerivePkgAddr("gno.land/r/demo/tok20-airdrop") std.TestSetOrigCaller(contractAddr) @@ -94,9 +89,9 @@ func TestDoubleClaim(t *testing.T) { proofs, err := tree.Proof(leaf) urequire.NoError(t, err) - err = tok20airdrop.Claim(leaf.(AirdropData), proofs) + err = tok20airdrop.Claim(leaf.(airdrop.Data), proofs) urequire.NoError(t, err) - err = tok20airdrop.Claim(leaf.(AirdropData), proofs) + err = tok20airdrop.Claim(leaf.(airdrop.Data), proofs) urequire.Error(t, err, ErrAlreadyClaimed.Error()) } diff --git a/examples/gno.land/r/demo/foo20-airdrop/airdrop.gno b/examples/gno.land/r/demo/foo20-airdrop/airdrop.gno index 46cfcc1c483..4d2b32f401c 100644 --- a/examples/gno.land/r/demo/foo20-airdrop/airdrop.gno +++ b/examples/gno.land/r/demo/foo20-airdrop/airdrop.gno @@ -1,6 +1,7 @@ package foo20airdrop import ( + "gno.land/p/demo/airdrop" "gno.land/p/demo/airdrop/grc20_merkle_airdrop" "gno.land/p/demo/grc/grc20" "gno.land/p/demo/merkle" @@ -25,16 +26,11 @@ func RegisterMerkleRoot(root string) { foo20airdrop = grc20_merkle_airdrop.NewMerkleAirdrop(root, token) } -func Claim(data grc20_merkle_airdrop.AirdropData, proofs []merkle.Node) { +func Claim(data airdrop.AirdropData, proofs []merkle.Node) { err := foo20airdrop.Claim(data, proofs) if err != nil { panic(err.Error()) } - - // err = token.Transfer(data.Address, data.Amount) - // if err != nil { - // panic(err.Error()) - // } } func TotalClaimed() uint64 { diff --git a/examples/gno.land/r/demo/foo20-airdrop/airdrop_test.gno b/examples/gno.land/r/demo/foo20-airdrop/airdrop_test.gno index b80ad269988..7266eb6c26a 100644 --- a/examples/gno.land/r/demo/foo20-airdrop/airdrop_test.gno +++ b/examples/gno.land/r/demo/foo20-airdrop/airdrop_test.gno @@ -4,38 +4,30 @@ import ( "std" "testing" + "gno.land/p/demo/airdrop" "gno.land/p/demo/airdrop/grc20_merkle_airdrop" "gno.land/p/demo/merkle" + "gno.land/p/demo/ufmt" "gno.land/p/demo/urequire" "gno.land/p/demo/users" "gno.land/r/demo/foo20" ) -func getLeaves() []merkle.Hashable { - var leaves = []grc20_merkle_airdrop.AirdropData{ - { - Address: "g1sw5xklxjjuv0yvuxy5f5s3l3mnj0nqq626a9wr", // albttx.gno - Amount: 10000, - }, - { - Address: "g1zyvskpxg5lv4qpygtuvp93zprrrjpk2exa9rfx", - Amount: 10000, - }, - { - Address: "g14szvkruznx49sxe4m9dmg3m8606sm6yp4a0wv8", - Amount: 10000, - }, - } +func getLeaves(size int) []merkle.Hashable { + leaves := make([]merkle.Hashable, size) - resp := make([]merkle.Hashable, len(leaves)) - for i, leave := range leaves { - resp[i] = leave + for i := 0; i < size; i++ { + leaves[i] = airdrop.NewData( + std.DerivePkgAddr(ufmt.Sprintf("gno.land/test/%d", i)), + 10000, + ) } - return resp + + return leaves } func TestRegisterMerkle(t *testing.T) { - leaves := getLeaves() + leaves := getLeaves(5) tree := merkle.NewTree(leaves) root := tree.Root() @@ -44,7 +36,7 @@ func TestRegisterMerkle(t *testing.T) { } func TestClaimAirdrop(t *testing.T) { - leaves := getLeaves() + leaves := getLeaves(5) contractAddr := std.DerivePkgAddr("gno.land/r/demo/foo20-airdrop") std.TestSetOrigCaller(contractAddr) @@ -60,9 +52,9 @@ func TestClaimAirdrop(t *testing.T) { sumClaimed := uint64(0) for _, leaf := range leaves { - data := leaf.(grc20_merkle_airdrop.AirdropData) - user := data.Address - sumClaimed += data.Amount + data := leaf.(airdrop.Data) + user := data.Address() + sumClaimed += data.Amount() proofs, err := tree.Proof(leaf) urequire.NoError(t, err) @@ -70,10 +62,10 @@ func TestClaimAirdrop(t *testing.T) { // claim airdrop Claim(data, proofs) - balance := foo20.BalanceOf(users.AddressOrName(data.Address)) + addr := users.AddressOrName(data.Address()) + balance := foo20.BalanceOf(addr) urequire.Equal(t, balance, uint64(10000)) } - ttClaimed := TotalClaimed() - urequire.Equal(t, ttClaimed, sumClaimed) + urequire.Equal(t, TotalClaimed(), sumClaimed) } From f6dfb03b69e5a324abb6b936cdcb55e7666da5ee Mon Sep 17 00:00:00 2001 From: albttx Date: Fri, 4 Oct 2024 14:40:36 +0100 Subject: [PATCH 06/17] chore: fmt --- .../demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno | 2 -- .../airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno | 1 - examples/gno.land/r/demo/foo20-airdrop/airdrop_test.gno | 1 - 3 files changed, 4 deletions(-) diff --git a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno index 3618bc39942..0264866ed0b 100644 --- a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno +++ b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno @@ -3,9 +3,7 @@ package grc20_merkle_airdrop import ( "crypto/sha256" "encoding/hex" - "encoding/json" "errors" - "std" "gno.land/p/demo/airdrop" "gno.land/p/demo/avl" diff --git a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno index 0dd2d7cbf9b..314ad191058 100644 --- a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno +++ b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno @@ -9,7 +9,6 @@ import ( "gno.land/p/demo/merkle" "gno.land/p/demo/ufmt" "gno.land/p/demo/urequire" - "gno.land/p/demo/users" ) func getLeaves(size int) []merkle.Hashable { diff --git a/examples/gno.land/r/demo/foo20-airdrop/airdrop_test.gno b/examples/gno.land/r/demo/foo20-airdrop/airdrop_test.gno index 7266eb6c26a..82a6ff7b87c 100644 --- a/examples/gno.land/r/demo/foo20-airdrop/airdrop_test.gno +++ b/examples/gno.land/r/demo/foo20-airdrop/airdrop_test.gno @@ -5,7 +5,6 @@ import ( "testing" "gno.land/p/demo/airdrop" - "gno.land/p/demo/airdrop/grc20_merkle_airdrop" "gno.land/p/demo/merkle" "gno.land/p/demo/ufmt" "gno.land/p/demo/urequire" From d56116804c0560b4e72c93808e3d84340aa55276 Mon Sep 17 00:00:00 2001 From: albttx Date: Fri, 4 Oct 2024 17:20:10 +0100 Subject: [PATCH 07/17] chore: gno mod tidy --- examples/gno.land/p/demo/airdrop/gno.mod | 1 + .../p/demo/airdrop/grc20_merkle_airdrop/gno.mod | 9 +++++++++ examples/gno.land/r/demo/foo20-airdrop/gno.mod | 11 +++++++++++ 3 files changed, 21 insertions(+) create mode 100644 examples/gno.land/p/demo/airdrop/gno.mod diff --git a/examples/gno.land/p/demo/airdrop/gno.mod b/examples/gno.land/p/demo/airdrop/gno.mod new file mode 100644 index 00000000000..3ccb8f6a21a --- /dev/null +++ b/examples/gno.land/p/demo/airdrop/gno.mod @@ -0,0 +1 @@ +module gno.land/p/demo/airdrop diff --git a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/gno.mod b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/gno.mod index 66e90798ad1..6b0bb6790ee 100644 --- a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/gno.mod +++ b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/gno.mod @@ -1 +1,10 @@ module gno.land/p/demo/airdrop/grc20_merkle_airdrop + +require ( + gno.land/p/demo/airdrop v0.0.0-latest + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/grc/grc20 v0.0.0-latest + gno.land/p/demo/merkle v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest + gno.land/p/demo/urequire v0.0.0-latest +) diff --git a/examples/gno.land/r/demo/foo20-airdrop/gno.mod b/examples/gno.land/r/demo/foo20-airdrop/gno.mod index d1e3892da23..f0e4ec1ffd7 100644 --- a/examples/gno.land/r/demo/foo20-airdrop/gno.mod +++ b/examples/gno.land/r/demo/foo20-airdrop/gno.mod @@ -1 +1,12 @@ module gno.land/r/demo/foo20-airdrop + +require ( + gno.land/p/demo/airdrop v0.0.0-latest + gno.land/p/demo/airdrop/grc20_merkle_airdrop v0.0.0-latest + gno.land/p/demo/grc/grc20 v0.0.0-latest + gno.land/p/demo/merkle v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest + gno.land/p/demo/urequire v0.0.0-latest + gno.land/p/demo/users v0.0.0-latest + gno.land/r/demo/foo20 v0.0.0-latest +) From daea1e1e21d3eeb24f1bf3bf7603a659a1f2e186 Mon Sep 17 00:00:00 2001 From: albttx Date: Fri, 4 Oct 2024 17:27:26 +0100 Subject: [PATCH 08/17] chore: don't use json --- examples/gno.land/p/demo/airdrop/airdrop.gno | 8 +++----- examples/gno.land/p/demo/airdrop/gno.mod | 2 ++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/gno.land/p/demo/airdrop/airdrop.gno b/examples/gno.land/p/demo/airdrop/airdrop.gno index 226dffe06de..9f56c8a5667 100644 --- a/examples/gno.land/p/demo/airdrop/airdrop.gno +++ b/examples/gno.land/p/demo/airdrop/airdrop.gno @@ -1,8 +1,9 @@ package airdrop import ( - "encoding/json" "std" + + "gno.land/p/demo/ufmt" ) type AirdropData interface { @@ -27,10 +28,7 @@ func NewData(addr std.Address, amount uint64) Data { } func (d Data) Bytes() []byte { - out, err := json.Marshal(d.data) - if err != nil { - panic(err) - } + out := ufmt.Sprintf(`{"address":"%s","amount":"%s"}`, d.data.Address, d.data.Amount) return []byte(out) } diff --git a/examples/gno.land/p/demo/airdrop/gno.mod b/examples/gno.land/p/demo/airdrop/gno.mod index 3ccb8f6a21a..37fa09c4d04 100644 --- a/examples/gno.land/p/demo/airdrop/gno.mod +++ b/examples/gno.land/p/demo/airdrop/gno.mod @@ -1 +1,3 @@ module gno.land/p/demo/airdrop + +require gno.land/p/demo/ufmt v0.0.0-latest From 6fd24f13a25652fcd8eae6c722b7dcd9820fa117 Mon Sep 17 00:00:00 2001 From: albttx Date: Fri, 4 Oct 2024 17:41:40 +0100 Subject: [PATCH 09/17] chore: rename --- .../gno.land/r/demo/{foo20-airdrop => foo20_airdrop}/airdrop.gno | 0 .../r/demo/{foo20-airdrop => foo20_airdrop}/airdrop_test.gno | 0 examples/gno.land/r/demo/{foo20-airdrop => foo20_airdrop}/gno.mod | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename examples/gno.land/r/demo/{foo20-airdrop => foo20_airdrop}/airdrop.gno (100%) rename examples/gno.land/r/demo/{foo20-airdrop => foo20_airdrop}/airdrop_test.gno (100%) rename examples/gno.land/r/demo/{foo20-airdrop => foo20_airdrop}/gno.mod (100%) diff --git a/examples/gno.land/r/demo/foo20-airdrop/airdrop.gno b/examples/gno.land/r/demo/foo20_airdrop/airdrop.gno similarity index 100% rename from examples/gno.land/r/demo/foo20-airdrop/airdrop.gno rename to examples/gno.land/r/demo/foo20_airdrop/airdrop.gno diff --git a/examples/gno.land/r/demo/foo20-airdrop/airdrop_test.gno b/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno similarity index 100% rename from examples/gno.land/r/demo/foo20-airdrop/airdrop_test.gno rename to examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno diff --git a/examples/gno.land/r/demo/foo20-airdrop/gno.mod b/examples/gno.land/r/demo/foo20_airdrop/gno.mod similarity index 100% rename from examples/gno.land/r/demo/foo20-airdrop/gno.mod rename to examples/gno.land/r/demo/foo20_airdrop/gno.mod From 93384011859c7647e18da30d4fe32f9a553b5a34 Mon Sep 17 00:00:00 2001 From: albttx Date: Fri, 4 Oct 2024 17:41:57 +0100 Subject: [PATCH 10/17] chore: rename --- examples/gno.land/r/demo/foo20_airdrop/gno.mod | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/examples/gno.land/r/demo/foo20_airdrop/gno.mod b/examples/gno.land/r/demo/foo20_airdrop/gno.mod index f0e4ec1ffd7..1413f70ea9e 100644 --- a/examples/gno.land/r/demo/foo20_airdrop/gno.mod +++ b/examples/gno.land/r/demo/foo20_airdrop/gno.mod @@ -1,12 +1 @@ -module gno.land/r/demo/foo20-airdrop - -require ( - gno.land/p/demo/airdrop v0.0.0-latest - gno.land/p/demo/airdrop/grc20_merkle_airdrop v0.0.0-latest - gno.land/p/demo/grc/grc20 v0.0.0-latest - gno.land/p/demo/merkle v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/urequire v0.0.0-latest - gno.land/p/demo/users v0.0.0-latest - gno.land/r/demo/foo20 v0.0.0-latest -) +module gno.land/r/demo/foo20_airdrop From ba85a46649fc0d5b4d5eb84e8c250b940586f69f Mon Sep 17 00:00:00 2001 From: albttx Date: Fri, 4 Oct 2024 17:43:25 +0100 Subject: [PATCH 11/17] chore: rename --- examples/gno.land/r/demo/foo20_airdrop/airdrop.gno | 2 +- examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/gno.land/r/demo/foo20_airdrop/airdrop.gno b/examples/gno.land/r/demo/foo20_airdrop/airdrop.gno index 4d2b32f401c..e282ebee27c 100644 --- a/examples/gno.land/r/demo/foo20_airdrop/airdrop.gno +++ b/examples/gno.land/r/demo/foo20_airdrop/airdrop.gno @@ -1,4 +1,4 @@ -package foo20airdrop +package foo20_airdrop import ( "gno.land/p/demo/airdrop" diff --git a/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno b/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno index 82a6ff7b87c..e602a5522d2 100644 --- a/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno +++ b/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno @@ -1,4 +1,4 @@ -package foo20airdrop +package foo20_airdrop import ( "std" From 3f19a92c33e13021c10022addea9f233a73cdc20 Mon Sep 17 00:00:00 2001 From: albttx Date: Fri, 4 Oct 2024 17:55:29 +0100 Subject: [PATCH 12/17] chore: gno mod tidy --- examples/gno.land/r/demo/foo20_airdrop/gno.mod | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/examples/gno.land/r/demo/foo20_airdrop/gno.mod b/examples/gno.land/r/demo/foo20_airdrop/gno.mod index 1413f70ea9e..7e179f97985 100644 --- a/examples/gno.land/r/demo/foo20_airdrop/gno.mod +++ b/examples/gno.land/r/demo/foo20_airdrop/gno.mod @@ -1 +1,12 @@ module gno.land/r/demo/foo20_airdrop + +require ( + gno.land/p/demo/airdrop v0.0.0-latest + gno.land/p/demo/airdrop/grc20_merkle_airdrop v0.0.0-latest + gno.land/p/demo/grc/grc20 v0.0.0-latest + gno.land/p/demo/merkle v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest + gno.land/p/demo/urequire v0.0.0-latest + gno.land/p/demo/users v0.0.0-latest + gno.land/r/demo/foo20 v0.0.0-latest +) From ea69f6c58314901e5ead1381d9c3029f5ce50aea Mon Sep 17 00:00:00 2001 From: albttx Date: Thu, 17 Oct 2024 11:35:02 +0100 Subject: [PATCH 13/17] wip --- examples/gno.land/r/demo/foo20_airdrop/airdrop.gno | 11 ++++++++--- .../gno.land/r/demo/foo20_airdrop/airdrop_test.gno | 12 ++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/examples/gno.land/r/demo/foo20_airdrop/airdrop.gno b/examples/gno.land/r/demo/foo20_airdrop/airdrop.gno index e282ebee27c..c99b8a79f25 100644 --- a/examples/gno.land/r/demo/foo20_airdrop/airdrop.gno +++ b/examples/gno.land/r/demo/foo20_airdrop/airdrop.gno @@ -5,20 +5,18 @@ import ( "gno.land/p/demo/airdrop/grc20_merkle_airdrop" "gno.land/p/demo/grc/grc20" "gno.land/p/demo/merkle" + "gno.land/p/demo/ufmt" "gno.land/r/demo/foo20" ) var ( token grc20.Token - // admin std.Address = "g1sw5xklxjjuv0yvuxy5f5s3l3mnj0nqq626a9wr" // albttx.gno - foo20airdrop *grc20_merkle_airdrop.MerkleAirdrop ) func RegisterMerkleRoot(root string) { token = foo20.Token() - foo20airdrop = nil if foo20airdrop != nil { panic("foo20 airdrop merkle root is already registered") @@ -36,3 +34,10 @@ func Claim(data airdrop.AirdropData, proofs []merkle.Node) { func TotalClaimed() uint64 { return foo20airdrop.TotalClaimed() } + +func Render(path string) string { + if foo20airdrop == nil { + return "Airdrop is not registered yet" + } + return ufmt.Sprintf("total claimed: %d", foo20airdrop.TotalClaimed()) +} diff --git a/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno b/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno index e602a5522d2..593fe09b0f8 100644 --- a/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno +++ b/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno @@ -12,6 +12,10 @@ import ( "gno.land/r/demo/foo20" ) +func reset() { + foo20airdrop = nil +} + func getLeaves(size int) []merkle.Hashable { leaves := make([]merkle.Hashable, size) @@ -21,20 +25,28 @@ func getLeaves(size int) []merkle.Hashable { 10000, ) } + leaves = append(leaves, airdrop.NewData( + "g1sw5xklxjjuv0yvuxy5f5s3l3mnj0nqq626a9wr", + 1000, + )) return leaves } func TestRegisterMerkle(t *testing.T) { + defer reset() leaves := getLeaves(5) tree := merkle.NewTree(leaves) root := tree.Root() + println(root) + RegisterMerkleRoot(root) } func TestClaimAirdrop(t *testing.T) { + defer reset() leaves := getLeaves(5) contractAddr := std.DerivePkgAddr("gno.land/r/demo/foo20-airdrop") From 3d9ea6ed4bad9e32226492b9cefa40da39e3e0d8 Mon Sep 17 00:00:00 2001 From: albttx Date: Fri, 8 Nov 2024 13:48:29 +0000 Subject: [PATCH 14/17] wip --- examples/gno.land/p/demo/airdrop/airdrop.gno | 2 +- .../grc20_merkle_airdrop.gno | 1 + .../gno.land/r/demo/foo20_airdrop/airdrop.gno | 50 ++ .../r/demo/foo20_airdrop/airdrop_test.gno | 77 ++- misc/js-merkletree/package.json | 17 + misc/js-merkletree/src/index.js | 59 ++ misc/js-merkletree/test/test.js | 47 ++ misc/js-merkletree/yarn.lock | 647 ++++++++++++++++++ package.json | 6 + yarn.lock | 82 +++ 10 files changed, 982 insertions(+), 6 deletions(-) create mode 100644 misc/js-merkletree/package.json create mode 100644 misc/js-merkletree/src/index.js create mode 100644 misc/js-merkletree/test/test.js create mode 100644 misc/js-merkletree/yarn.lock create mode 100644 package.json create mode 100644 yarn.lock diff --git a/examples/gno.land/p/demo/airdrop/airdrop.gno b/examples/gno.land/p/demo/airdrop/airdrop.gno index 9f56c8a5667..51b126ccbf3 100644 --- a/examples/gno.land/p/demo/airdrop/airdrop.gno +++ b/examples/gno.land/p/demo/airdrop/airdrop.gno @@ -28,7 +28,7 @@ func NewData(addr std.Address, amount uint64) Data { } func (d Data) Bytes() []byte { - out := ufmt.Sprintf(`{"address":"%s","amount":"%s"}`, d.data.Address, d.data.Amount) + out := ufmt.Sprintf(`{"address":"%s","amount":"%d"}`, d.data.Address, d.data.Amount) return []byte(out) } diff --git a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno index 0264866ed0b..a99fbcd85e4 100644 --- a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno +++ b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno @@ -43,6 +43,7 @@ func (ma *MerkleAirdrop) Claim(data airdrop.AirdropData, proofs []merkle.Node) e if ma.claimed.Has(hash) { return ErrAlreadyClaimed } + println(proofs) if !merkle.Verify(ma.root, data, proofs) { return ErrInvalidProof diff --git a/examples/gno.land/r/demo/foo20_airdrop/airdrop.gno b/examples/gno.land/r/demo/foo20_airdrop/airdrop.gno index c99b8a79f25..2e5eaae1d83 100644 --- a/examples/gno.land/r/demo/foo20_airdrop/airdrop.gno +++ b/examples/gno.land/r/demo/foo20_airdrop/airdrop.gno @@ -1,9 +1,13 @@ package foo20_airdrop import ( + "std" + "strconv" + "gno.land/p/demo/airdrop" "gno.land/p/demo/airdrop/grc20_merkle_airdrop" "gno.land/p/demo/grc/grc20" + "gno.land/p/demo/json" "gno.land/p/demo/merkle" "gno.land/p/demo/ufmt" "gno.land/r/demo/foo20" @@ -31,6 +35,51 @@ func Claim(data airdrop.AirdropData, proofs []merkle.Node) { } } +type ClaimRequest struct { + Address string `json:"address"` + Amount string `json:"amount"` + Proof []struct { + Position float64 `json:"position"` + Data string `json:"data"` + } `json:"proof"` +} + +func (req ClaimRequest) MustGetAmount() uint64 { + n, err := strconv.ParseInt(req.Amount, 10, 64) + if err != nil { + panic("failed to parse amount: " + req.Amount) + } + return uint64(n) +} + +func ClaimJSON(in string) { + n, err := json.Unmarshal([]byte(in)) + if err != nil { + panic(err.Error()) + } + + req := &ClaimRequest{ + Address: n.MustKey("address").MustString(), + Amount: n.MustKey("amount").MustString(), + } + + arr := n.MustKey("proof").MustArray() + proof := make([]merkle.Node, len(arr)) + + for i, e := range arr { + pos := e.MustKey("position").MustNumeric() + data := e.MustKey("data").MustString() + + proof[i] = merkle.NewNode([]byte(data), uint8(pos)) + } + + data := airdrop.NewData(std.Address(req.Address), req.MustGetAmount()) + // println(data) + // println(req, proof) + + Claim(data, proof) +} + func TotalClaimed() uint64 { return foo20airdrop.TotalClaimed() } @@ -39,5 +88,6 @@ func Render(path string) string { if foo20airdrop == nil { return "Airdrop is not registered yet" } + return ufmt.Sprintf("total claimed: %d", foo20airdrop.TotalClaimed()) } diff --git a/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno b/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno index 593fe09b0f8..348127b0595 100644 --- a/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno +++ b/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno @@ -5,6 +5,7 @@ import ( "testing" "gno.land/p/demo/airdrop" + "gno.land/p/demo/json" "gno.land/p/demo/merkle" "gno.land/p/demo/ufmt" "gno.land/p/demo/urequire" @@ -21,14 +22,14 @@ func getLeaves(size int) []merkle.Hashable { for i := 0; i < size; i++ { leaves[i] = airdrop.NewData( - std.DerivePkgAddr(ufmt.Sprintf("gno.land/test/%d", i)), + std.DerivePkgAddr(ufmt.Sprintf("gno.land/r/test/%d", i)), 10000, ) } - leaves = append(leaves, airdrop.NewData( - "g1sw5xklxjjuv0yvuxy5f5s3l3mnj0nqq626a9wr", - 1000, - )) + // leaves = append(leaves, airdrop.NewData( + // "g1sw5xklxjjuv0yvuxy5f5s3l3mnj0nqq626a9wr", + // 1000, + // )) return leaves } @@ -80,3 +81,69 @@ func TestClaimAirdrop(t *testing.T) { urequire.Equal(t, TotalClaimed(), sumClaimed) } + +func TestClaimJSONAirdrop(t *testing.T) { + defer reset() + tests := []struct { + name string + root string + in string + }{ + { + name: "10 leaves", + root: "0cce01ece896de259789bbbef8ce0481c6dbde1fa67dbe08089d66d26ec8e9a5", + in: `{"address":"g1tvhw8hqz272fglt8p5efwj226r3uqf064u3wxk","amount":"10000","proof":[{"data":"942abf9387714a4a9c3348a7803d22f8964e1eb8fba0b74fdd20b4e67aa07ffe","position":1},{"data":"d4aaaeb914c8367099ad24975c70a2a3d5af91ab3decbe7033496fbf76fdc176","position":0},{"data":"9f52c2dda050e932ca109d2a5a025acd73ed258c5d2b1b51dfbda3896bc60a0a","position":1},{"data":"8cb6b56e7db744b79d7f0da4532404c65c5332f2b44b58fa006fe5107848a110","position":0}]}`, + }, + } + + // leaves := getLeaves(10) + + // contractAddr := std.DerivePkgAddr("gno.land/r/demo/foo20-airdrop") + // std.TestSetOrigCaller(contractAddr) + + // for _, leave := range leaves { + // // Get 10k token + // foo20.Faucet() + // } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + RegisterMerkleRoot(tt.root) + + ClaimJSON(tt.in) + + // println(ufmt.Sprintf("%s", req)) + }) + } + + // instantiate foo20 airdrop contract + // RegisterMerkleRoot() + + // sumClaimed := uint64(0) + // for _, leaf := range leaves { + // data := leaf.(airdrop.Data) + // user := data.Address() + // sumClaimed += data.Amount() + + // req := ClaimRequest{ + // Address: string(data.Address()), + // Amount: data.Amount(), + // } + + // in, err := json.Marshal(req) + // urequire.NoError(t, err) + // // println(in) + + // proofs, err := tree.Proof(leaf) + // urequire.NoError(t, err) + + // // claim airdrop + // Claim(data, proofs) + + // addr := users.AddressOrName(data.Address()) + // balance := foo20.BalanceOf(addr) + // urequire.Equal(t, balance, uint64(10000)) + // } + + // urequire.Equal(t, TotalClaimed(), sumClaimed) +} diff --git a/misc/js-merkletree/package.json b/misc/js-merkletree/package.json new file mode 100644 index 00000000000..eaf1ffa6db5 --- /dev/null +++ b/misc/js-merkletree/package.json @@ -0,0 +1,17 @@ +{ + "name": "js-merkletree", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "dependencies": { + "crypto-js": "^4.2.0", + "merkletreejs": "^0.4.0" + }, + "scripts": { + "start": "node ./src/index.js", + "test": "mocha" + }, + "devDependencies": { + "mocha": "^10.7.3" + } +} diff --git a/misc/js-merkletree/src/index.js b/misc/js-merkletree/src/index.js new file mode 100644 index 00000000000..9109db4c8ff --- /dev/null +++ b/misc/js-merkletree/src/index.js @@ -0,0 +1,59 @@ +const { MerkleTree } = require("merkletreejs"); +const crypto = require("crypto"); +const SHA256 = require("crypto-js/sha256"); +const secp256k1 = require("secp256k1"); +const { bech32 } = require("bech32"); + +// This function reproduce the output of std.DerivePkgAddr +function derive_pkg_addr(str) { + const hash = crypto + .createHash("sha256") + .update("pkgPath:" + str) + .digest(); + + let hash_bytes = new Uint8Array(hash).slice(0, 20); + + const words = bech32.toWords(hash_bytes); + return bech32.encode("g", words); +} + +// Start script + +for (size of [1, 3, 10, 1000]) { + console.log(`[INFO] Start with size ${size}`); + + const addresses = Array.from({ length: size }, (_, i) => + derive_pkg_addr(`gno.land/r/test/${i}`), + ); + + const leaves = addresses.map((addr) => + SHA256(JSON.stringify({ address: addr, amount: "10000" })), + ); + + const tree = new MerkleTree(leaves, SHA256); + const root = tree.getRoot().toString("hex"); + + console.log(root); + // const proof = tree.getProof(leaves[5]).map((p) => ({ + // data: p.data.toString("hex"), + // position: p.position === "left" ? 1 : 0, + // })); +} + +// const tree = new MerkleTree(leaves, SHA256); +// const root = tree.getRoot().toString("hex"); + +// const proof = tree.getProof(leaves[5]).map((p) => ({ +// data: p.data.toString("hex"), +// position: p.position === "left" ? 1 : 0, +// })); + +// const req = { +// address: derive_pkg_addr("gno.land/r/test/5"), +// amount: "10000", +// proof: proof, +// }; + +// console.log("req", JSON.stringify(req)); + +// console.log("root", root); diff --git a/misc/js-merkletree/test/test.js b/misc/js-merkletree/test/test.js new file mode 100644 index 00000000000..90c43911d1d --- /dev/null +++ b/misc/js-merkletree/test/test.js @@ -0,0 +1,47 @@ +const { MerkleTree } = require("merkletreejs"); +const SHA256 = require("crypto-js/sha256"); + +var assert = require("assert"); + +describe("Generate Tree", function () { + const tests = [ + { + size: 1, + expected: + "cf9f824bce7f5bc63d557b23591f58577f53fe29f974a615bdddbd0140f912f4", + }, + { + size: 3, + expected: + "1a4a5f0fa267244bf9f74a63fdf2a87eed5e97e4bd104a9e94728c8fb5442177", + }, + { + size: 10, + expected: + "cd8a40502b0b92bf58e7432a5abb2d8b60121cf2b7966d6ebaf103f907a1bc21", + }, + { + size: 1000, + expected: + "fa533d2efdf12be26bc410dfa42936ac63361324e35e9b1ff54d422a1dd2388b", + }, + ]; + + for (let tt of tests) { + describe(`size_${tt.size}`, function () { + it(`should return ${tt.expected}`, function () { + const leaves = Array.from({ length: tt.size }, (_, i) => + SHA256(`node_${i}`), + ); + + const tree = new MerkleTree(leaves, SHA256, {}); + const leaf = SHA256(leaves[0]); + + const proof = tree.getProof(leaf); + const root = tree.getRoot().toString("hex"); + + assert.equal(root, tt.expected); + }); + }); + } +}); diff --git a/misc/js-merkletree/yarn.lock b/misc/js-merkletree/yarn.lock new file mode 100644 index 00000000000..8f7bb48be52 --- /dev/null +++ b/misc/js-merkletree/yarn.lock @@ -0,0 +1,647 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ethereumjs/rlp@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-4.0.1.tgz#626fabfd9081baab3d0a3074b0c7ecaf674aaa41" + integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw== + +"@ethereumjs/util@^8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-8.1.0.tgz#299df97fb6b034e0577ce9f94c7d9d1004409ed4" + integrity sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA== + dependencies: + "@ethereumjs/rlp" "^4.0.1" + ethereum-cryptography "^2.0.0" + micro-ftch "^0.3.1" + +"@noble/curves@1.4.2", "@noble/curves@~1.4.0": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" + integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== + dependencies: + "@noble/hashes" "1.4.0" + +"@noble/hashes@1.4.0", "@noble/hashes@~1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" + integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== + +"@noble/hashes@^1.4.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.5.0.tgz#abadc5ca20332db2b1b2aa3e496e9af1213570b0" + integrity sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA== + +"@scure/base@~1.1.6": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1" + integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg== + +"@scure/bip32@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.4.0.tgz#4e1f1e196abedcef395b33b9674a042524e20d67" + integrity sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg== + dependencies: + "@noble/curves" "~1.4.0" + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" + +"@scure/bip39@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.3.0.tgz#0f258c16823ddd00739461ac31398b4e7d6a18c3" + integrity sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ== + dependencies: + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" + +ansi-colors@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +bignumber.js@^9.0.1: + version "9.1.2" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c" + integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug== + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +bn.js@4.11.6: + version "4.11.6" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" + integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== + +bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +browser-stdout@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +buffer-reverse@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-reverse/-/buffer-reverse-1.0.1.tgz#49283c8efa6f901bc01fa3304d06027971ae2f60" + integrity sha512-M87YIUBsZ6N924W57vDwT/aOu8hw7ZgdByz6ijksLjmHJELBASmYTTlNHRgjE+pTsT9oJXGaDSgqqwfdHotDUg== + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chokidar@^3.5.3: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +crypto-js@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631" + integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q== + +debug@^4.3.5: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +diff@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +escalade@^3.1.1: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +ethereum-bloom-filters@^1.0.6: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.2.0.tgz#8294f074c1a6cbd32c39d2cc77ce86ff14797dab" + integrity sha512-28hyiE7HVsWubqhpVLVmZXFd4ITeHi+BUu05o9isf0GUpMtzBUi+8/gFrGaGYzvGAJQmJ3JKj77Mk9G98T84rA== + dependencies: + "@noble/hashes" "^1.4.0" + +ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.2: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz#58f2810f8e020aecb97de8c8c76147600b0b8ccf" + integrity sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg== + dependencies: + "@noble/curves" "1.4.2" + "@noble/hashes" "1.4.0" + "@scure/bip32" "1.4.0" + "@scure/bip39" "1.3.0" + +ethjs-unit@0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" + integrity sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw== + dependencies: + bn.js "4.11.6" + number-to-bn "1.7.0" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hex-prefixed@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +merkletreejs@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/merkletreejs/-/merkletreejs-0.4.0.tgz#40514dd8b5f511b3f136aeea3ff90d74d5604112" + integrity sha512-a48Ta5kWiVNBgeEbZVMm6FB1hBlp6vEuou/XnZdlkmd2zq6NZR6Sh2j+kR1B0iOZIXrTMcigBYzZ39MLdYhm1g== + dependencies: + bignumber.js "^9.0.1" + buffer-reverse "^1.0.1" + crypto-js "^4.2.0" + treeify "^1.1.0" + web3-utils "^1.3.4" + +micro-ftch@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/micro-ftch/-/micro-ftch-0.3.1.tgz#6cb83388de4c1f279a034fb0cf96dfc050853c5f" + integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== + +minimatch@^5.0.1, minimatch@^5.1.6: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +mocha@^10.7.3: + version "10.7.3" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.7.3.tgz#ae32003cabbd52b59aece17846056a68eb4b0752" + integrity sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A== + dependencies: + ansi-colors "^4.1.3" + browser-stdout "^1.3.1" + chokidar "^3.5.3" + debug "^4.3.5" + diff "^5.2.0" + escape-string-regexp "^4.0.0" + find-up "^5.0.0" + glob "^8.1.0" + he "^1.2.0" + js-yaml "^4.1.0" + log-symbols "^4.1.0" + minimatch "^5.1.6" + ms "^2.1.3" + serialize-javascript "^6.0.2" + strip-json-comments "^3.1.1" + supports-color "^8.1.1" + workerpool "^6.5.1" + yargs "^16.2.0" + yargs-parser "^20.2.9" + yargs-unparser "^2.0.0" + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +number-to-bn@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" + integrity sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig== + dependencies: + bn.js "4.11.6" + strip-hex-prefix "1.0.0" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +serialize-javascript@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-hex-prefix@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" + integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A== + dependencies: + is-hex-prefixed "1.0.0" + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +treeify@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8" + integrity sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A== + +utf8@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== + +web3-utils@^1.3.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.4.tgz#0daee7d6841641655d8b3726baf33b08eda1cbec" + integrity sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A== + dependencies: + "@ethereumjs/util" "^8.1.0" + bn.js "^5.2.1" + ethereum-bloom-filters "^1.0.6" + ethereum-cryptography "^2.1.2" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" + +workerpool@^6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" + integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yargs-parser@^20.2.2, yargs-parser@^20.2.9: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/package.json b/package.json new file mode 100644 index 00000000000..d3d6f952d84 --- /dev/null +++ b/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "bech32": "^2.0.0", + "secp256k1": "^5.0.1" + } +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000000..f57f726370a --- /dev/null +++ b/yarn.lock @@ -0,0 +1,82 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +bech32@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-2.0.0.tgz#078d3686535075c8c79709f054b1b226a133b355" + integrity sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg== + +bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +elliptic@^6.5.7: + version "6.5.7" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b" + integrity sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +inherits@^2.0.3, inherits@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +node-addon-api@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" + integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA== + +node-gyp-build@^4.2.0: + version "4.8.2" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.2.tgz#4f802b71c1ab2ca16af830e6c1ea7dd1ad9496fa" + integrity sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw== + +secp256k1@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-5.0.1.tgz#dc2c86187d48ff2da756f0f7e96417ee03c414b1" + integrity sha512-lDFs9AAIaWP9UCdtWrotXWWF9t8PWgQDcxqgAnpM9rMqxb3Oaq2J0thzPVSxBwdJgyQtkU/sYtFtbM1RSt/iYA== + dependencies: + elliptic "^6.5.7" + node-addon-api "^5.0.0" + node-gyp-build "^4.2.0" From 25bf1e125f6fac303000d6c2f6b9a35b524036fc Mon Sep 17 00:00:00 2001 From: albttx Date: Thu, 14 Nov 2024 15:08:42 +0000 Subject: [PATCH 15/17] fixup --- .../grc20_merkle_airdrop.gno | 11 +-- .../gno.land/r/demo/foo20_airdrop/airdrop.gno | 12 +-- .../r/demo/foo20_airdrop/airdrop_test.gno | 76 ++++++------------- misc/js-merkletree/src/index.js | 49 ++++-------- 4 files changed, 46 insertions(+), 102 deletions(-) diff --git a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno index a99fbcd85e4..722ac19f55a 100644 --- a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno +++ b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop.gno @@ -19,11 +19,11 @@ var ( type MerkleAirdrop struct { root string - token grc20.Token + token grc20.Teller claimed *avl.Tree } -func NewMerkleAirdrop(merkleroot string, token grc20.Token) *MerkleAirdrop { +func NewMerkleAirdrop(merkleroot string, token grc20.Teller) *MerkleAirdrop { return &MerkleAirdrop{ root: merkleroot, @@ -43,18 +43,11 @@ func (ma *MerkleAirdrop) Claim(data airdrop.AirdropData, proofs []merkle.Node) e if ma.claimed.Has(hash) { return ErrAlreadyClaimed } - println(proofs) if !merkle.Verify(ma.root, data, proofs) { return ErrInvalidProof } - // THIS WORKS - // foo20.Transfer(users.AddressOrName(data.Address), data.Amount) - - // THIS DOES NOT WORK - // foo20.GRC20().Transfer(data.Address, data.Amount) - err := ma.token.Transfer(data.Address(), data.Amount()) if err != nil { return err diff --git a/examples/gno.land/r/demo/foo20_airdrop/airdrop.gno b/examples/gno.land/r/demo/foo20_airdrop/airdrop.gno index 2e5eaae1d83..9b3d97e4a42 100644 --- a/examples/gno.land/r/demo/foo20_airdrop/airdrop.gno +++ b/examples/gno.land/r/demo/foo20_airdrop/airdrop.gno @@ -1,6 +1,7 @@ package foo20_airdrop import ( + "encoding/hex" "std" "strconv" @@ -14,13 +15,13 @@ import ( ) var ( - token grc20.Token + token grc20.Teller foo20airdrop *grc20_merkle_airdrop.MerkleAirdrop ) func RegisterMerkleRoot(root string) { - token = foo20.Token() + token = foo20.Token.RealmTeller() if foo20airdrop != nil { panic("foo20 airdrop merkle root is already registered") @@ -68,14 +69,15 @@ func ClaimJSON(in string) { for i, e := range arr { pos := e.MustKey("position").MustNumeric() - data := e.MustKey("data").MustString() + data, err := hex.DecodeString(e.MustKey("data").MustString()) + if err != nil { + panic(err.Error()) + } proof[i] = merkle.NewNode([]byte(data), uint8(pos)) } data := airdrop.NewData(std.Address(req.Address), req.MustGetAmount()) - // println(data) - // println(req, proof) Claim(data, proof) } diff --git a/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno b/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno index 348127b0595..6694562497a 100644 --- a/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno +++ b/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno @@ -26,10 +26,6 @@ func getLeaves(size int) []merkle.Hashable { 10000, ) } - // leaves = append(leaves, airdrop.NewData( - // "g1sw5xklxjjuv0yvuxy5f5s3l3mnj0nqq626a9wr", - // 1000, - // )) return leaves } @@ -41,8 +37,6 @@ func TestRegisterMerkle(t *testing.T) { tree := merkle.NewTree(leaves) root := tree.Root() - println(root) - RegisterMerkleRoot(root) } @@ -63,7 +57,7 @@ func TestClaimAirdrop(t *testing.T) { RegisterMerkleRoot(tree.Root()) sumClaimed := uint64(0) - for _, leaf := range leaves { + for i, leaf := range leaves { data := leaf.(airdrop.Data) user := data.Address() sumClaimed += data.Amount() @@ -90,60 +84,38 @@ func TestClaimJSONAirdrop(t *testing.T) { in string }{ { - name: "10 leaves", + name: "10 leaves-leaf5", root: "0cce01ece896de259789bbbef8ce0481c6dbde1fa67dbe08089d66d26ec8e9a5", - in: `{"address":"g1tvhw8hqz272fglt8p5efwj226r3uqf064u3wxk","amount":"10000","proof":[{"data":"942abf9387714a4a9c3348a7803d22f8964e1eb8fba0b74fdd20b4e67aa07ffe","position":1},{"data":"d4aaaeb914c8367099ad24975c70a2a3d5af91ab3decbe7033496fbf76fdc176","position":0},{"data":"9f52c2dda050e932ca109d2a5a025acd73ed258c5d2b1b51dfbda3896bc60a0a","position":1},{"data":"8cb6b56e7db744b79d7f0da4532404c65c5332f2b44b58fa006fe5107848a110","position":0}]}`, + in: `{ + "address": "g1tvhw8hqz272fglt8p5efwj226r3uqf064u3wxk", + "amount": "10000", + "proof": [ + { + "data": "942abf9387714a4a9c3348a7803d22f8964e1eb8fba0b74fdd20b4e67aa07ffe", + "position": 1 + }, + { + "data": "d4aaaeb914c8367099ad24975c70a2a3d5af91ab3decbe7033496fbf76fdc176", + "position": 0 + }, + { + "data": "9f52c2dda050e932ca109d2a5a025acd73ed258c5d2b1b51dfbda3896bc60a0a", + "position": 1 + }, + { + "data": "8cb6b56e7db744b79d7f0da4532404c65c5332f2b44b58fa006fe5107848a110", + "position": 0 + } + ] +}`, }, } - // leaves := getLeaves(10) - - // contractAddr := std.DerivePkgAddr("gno.land/r/demo/foo20-airdrop") - // std.TestSetOrigCaller(contractAddr) - - // for _, leave := range leaves { - // // Get 10k token - // foo20.Faucet() - // } - for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { RegisterMerkleRoot(tt.root) ClaimJSON(tt.in) - - // println(ufmt.Sprintf("%s", req)) }) } - - // instantiate foo20 airdrop contract - // RegisterMerkleRoot() - - // sumClaimed := uint64(0) - // for _, leaf := range leaves { - // data := leaf.(airdrop.Data) - // user := data.Address() - // sumClaimed += data.Amount() - - // req := ClaimRequest{ - // Address: string(data.Address()), - // Amount: data.Amount(), - // } - - // in, err := json.Marshal(req) - // urequire.NoError(t, err) - // // println(in) - - // proofs, err := tree.Proof(leaf) - // urequire.NoError(t, err) - - // // claim airdrop - // Claim(data, proofs) - - // addr := users.AddressOrName(data.Address()) - // balance := foo20.BalanceOf(addr) - // urequire.Equal(t, balance, uint64(10000)) - // } - - // urequire.Equal(t, TotalClaimed(), sumClaimed) } diff --git a/misc/js-merkletree/src/index.js b/misc/js-merkletree/src/index.js index 9109db4c8ff..df45539eea9 100644 --- a/misc/js-merkletree/src/index.js +++ b/misc/js-merkletree/src/index.js @@ -17,43 +17,20 @@ function derive_pkg_addr(str) { return bech32.encode("g", words); } -// Start script +const addresses = Array.from({ length: 10 }, (_, i) => + derive_pkg_addr(`gno.land/r/test/${i}`), +); -for (size of [1, 3, 10, 1000]) { - console.log(`[INFO] Start with size ${size}`); +const leaves = addresses.map((addr) => + SHA256(JSON.stringify({ address: addr, amount: "10000" })), +); - const addresses = Array.from({ length: size }, (_, i) => - derive_pkg_addr(`gno.land/r/test/${i}`), - ); +const tree = new MerkleTree(leaves, SHA256); +const root = tree.getRoot().toString("hex"); - const leaves = addresses.map((addr) => - SHA256(JSON.stringify({ address: addr, amount: "10000" })), - ); +const proof = tree.getProof(leaves[5]).map((p) => ({ + data: p.data.toString("hex"), + position: p.position === "left" ? 1 : 0, +})); - const tree = new MerkleTree(leaves, SHA256); - const root = tree.getRoot().toString("hex"); - - console.log(root); - // const proof = tree.getProof(leaves[5]).map((p) => ({ - // data: p.data.toString("hex"), - // position: p.position === "left" ? 1 : 0, - // })); -} - -// const tree = new MerkleTree(leaves, SHA256); -// const root = tree.getRoot().toString("hex"); - -// const proof = tree.getProof(leaves[5]).map((p) => ({ -// data: p.data.toString("hex"), -// position: p.position === "left" ? 1 : 0, -// })); - -// const req = { -// address: derive_pkg_addr("gno.land/r/test/5"), -// amount: "10000", -// proof: proof, -// }; - -// console.log("req", JSON.stringify(req)); - -// console.log("root", root); +console.log("proof", proof); From dff5cc3fd928e04055838ebe7aa356c8a980a576 Mon Sep 17 00:00:00 2001 From: albttx Date: Thu, 14 Nov 2024 15:09:35 +0000 Subject: [PATCH 16/17] chore: make fmt --- examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno b/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno index 6694562497a..2c2dba79e37 100644 --- a/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno +++ b/examples/gno.land/r/demo/foo20_airdrop/airdrop_test.gno @@ -5,7 +5,6 @@ import ( "testing" "gno.land/p/demo/airdrop" - "gno.land/p/demo/json" "gno.land/p/demo/merkle" "gno.land/p/demo/ufmt" "gno.land/p/demo/urequire" From f81a99a591d19b99fa5874aa0ae5c24fcff7cacb Mon Sep 17 00:00:00 2001 From: albttx Date: Thu, 14 Nov 2024 15:20:31 +0000 Subject: [PATCH 17/17] fix: p/demo/airdrop --- .../grc20_merkle_airdrop_test.gno | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno index 314ad191058..31d96021721 100644 --- a/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno +++ b/examples/gno.land/p/demo/airdrop/grc20_merkle_airdrop/grc20_merkle_airdrop_test.gno @@ -30,10 +30,10 @@ func TestRegisterMerkle(t *testing.T) { root := tree.Root() contractAddr := std.DerivePkgAddr("gno.land/r/demo/tok20-airdrop") - token := grc20.NewBanker("TOKEN", "TOK", 6) - token.Mint(contractAddr, 50000) // Airdrop contract + token, admin := grc20.NewToken("TOKEN", "TOK", 6) + admin.Mint(contractAddr, 50000) // Airdrop contract - tok20airdrop := NewMerkleAirdrop(root, token.Token()) + tok20airdrop := NewMerkleAirdrop(root, token.RealmTeller()) _ = tok20airdrop } @@ -46,10 +46,10 @@ func TestClaimAirdrop(t *testing.T) { root := tree.Root() // instantiate foo20 airdrop contract - token := grc20.NewBanker("TOKEN", "TOK", 6) - token.Mint(contractAddr, 50000) // Airdrop contract + token, admin := grc20.NewToken("TOKEN", "TOK", 6) + admin.Mint(contractAddr, 50000) // Airdrop contract - tok20airdrop := NewMerkleAirdrop(root, token.Token()) + tok20airdrop := NewMerkleAirdrop(root, token.RealmTeller()) sumClaimed := uint64(0) for _, leaf := range leaves { @@ -79,10 +79,10 @@ func TestDoubleClaim(t *testing.T) { std.TestSetOrigCaller(contractAddr) tree := merkle.NewTree(leaves) - token := grc20.NewBanker("TOKEN", "TOK", 6) - token.Mint(contractAddr, 50000) + token, admin := grc20.NewToken("TOKEN", "TOK", 6) + admin.Mint(contractAddr, 50000) - tok20airdrop := NewMerkleAirdrop(tree.Root(), token.Token()) + tok20airdrop := NewMerkleAirdrop(tree.Root(), token.RealmTeller()) leaf := leaves[0] proofs, err := tree.Proof(leaf)