Skip to content

Commit

Permalink
chore: updates for the faucet community bot (#400)
Browse files Browse the repository at this point in the history
Co-authored-by: Manfred Touron <94029+moul@users.noreply.github.com>
Co-authored-by: piux2 <>
  • Loading branch information
piux2 and moul authored Mar 12, 2023
1 parent 469b97a commit bd598a5
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 128 deletions.
67 changes: 50 additions & 17 deletions examples/gno.land/r/gnoland/faucet/admin.gno
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,77 @@ import (
"std"
)

func AdminSetInPause(inPause bool) error {
func AdminSetInPause(inPause bool) string {
if err := assertIsAdmin(); err != nil {
return err
return err.Error()
}
gInPause = inPause
return nil
return ""
}

func AdminSetMessage(message string) error {
func AdminSetMessage(message string) string {
if err := assertIsAdmin(); err != nil {
return err
return err.Error()
}
gMessage = message
return nil
return ""
}

func AdminSetPerTransferSend(send std.Coins) error {
func AdminSetTransferLimit(amount int64) string {
if err := assertIsAdmin(); err != nil {
return err
return err.Error()
}
gPerTransferSend = send
return nil
gLimit = std.Coin{Denom: "ugnot", Amount: amount}
return ""
}

func AdminSetAdminAddr(addr std.Address) error {
func AdminSetAdminAddr(addr std.Address) string {
if err := assertIsAdmin(); err != nil {
return err
return err.Error()
}
gAdminAddr = addr
return nil
return ""
}

func AdminSetControllerAddr(addr std.Address) error {
func AdminAddController(addr std.Address) string {
if err := assertIsAdmin(); err != nil {
return err
return err.Error()
}
gControllerAddr = addr
return nil

size := gControllers.Size()

if size >= gControllersSize {
return "can not add more controllers than allowed"
}

if gControllers.Has(addr.String()) {
return addr.String() + " exists, no need to add."
}

gControllers.Set(addr.String(), addr)

return ""
}

func AdminRemoveController(addr std.Address) string {
if err := assertIsAdmin(); err != nil {
return err.Error()
}

if !gControllers.Has(addr.String()) {
return addr.String() + " is not on the controller list"
}

_, ok := gControllers.Remove(addr.String())

// it not should happen.
// we will check anyway to prevent issues in the underline implementation.

if !ok {
return addr.String() + " is not on the controller list"
}

return ""
}

func assertIsAdmin() error {
Expand Down
59 changes: 41 additions & 18 deletions examples/gno.land/r/gnoland/faucet/faucet.gno
Original file line number Diff line number Diff line change
Expand Up @@ -4,65 +4,88 @@ import (
"errors"
"std"

"gno.land/p/demo/avl"
"gno.land/p/demo/ufmt"
)

var (
// configurable by admin.
gAdminAddr std.Address = "g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq"
gControllerAddr std.Address = "g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq"
gPerTransferSend = std.Coins{std.Coin{"ugnot", 1000000}}
gAdminAddr std.Address = std.Address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
gControllers = avl.NewTree()
gControllersSize = 10 // limit it to 10
gInPause = false
gMessage = "# Community Faucet.\n\n"

// internal vars, for stats.
gTotalTransferred std.Coins
gTotalTransfers = uint(0)

// per request limit, 350 gnot
gLimit std.Coin = std.Coin{"ugnot", 350000000}
)

func Transfer(to std.Address) error {
func Transfer(to std.Address, send int64) string {
if err := assertIsController(); err != nil {
return err
return err.Error()
}

if gInPause {
return errors.New("faucet in pause")
return errors.New("faucet in pause").Error()
}

send := gPerTransferSend
// limit the per request
if send > gLimit.Amount {
return errors.New("Per request limit " + gLimit.String() + " exceed").Error()
}
sendCoins := std.Coins{std.Coin{Denom: "ugnot", Amount: send}}

gTotalTransferred = gTotalTransferred.Add(send)
gTotalTransferred = gTotalTransferred.Add(sendCoins)
gTotalTransfers++

banker := std.GetBanker(std.BankerTypeOrigSend)
banker := std.GetBanker(std.BankerTypeRealmSend)
pkgaddr := std.GetOrigPkgAddr()
banker.SendCoins(pkgaddr, to, send)
return nil
banker.SendCoins(pkgaddr, to, sendCoins)
return ""
}

func GetPerTransferLimit() int64 {
return gLimit.Amount
}

func Render(path string) string {
banker := std.GetBanker(std.BankerTypeOrigSend)
banker := std.GetBanker(std.BankerTypeRealmSend)
balance := banker.GetCoins(std.GetOrigPkgAddr())

output := gMessage
output := path + gMessage
if gInPause {
output += "Status: inactive.\n"
} else {
output += "Status: active.\n"
}
output += ufmt.Sprintf("Balance: %s.\n", balance.String())
output += ufmt.Sprintf("Rewarded: %s (in %d times).\n", gTotalTransferred.String(), gTotalTransfers)
output += ufmt.Sprintf("Total transfers: %s (in %d times).\n\n", gTotalTransferred.String(), gTotalTransfers)

if path == "?debug" {
output += ufmt.Sprintf("Admin: %s, Controller: %s\n", gAdminAddr.String(), gControllerAddr.String())
output += "Package address: " + std.GetOrigPkgAddr().String() + "\n\n"
output += ufmt.Sprintf("Admin: %s\n\n ", gAdminAddr.String())
output += ufmt.Sprintf("Controllers:\n\n ")

for i := 0; i < gControllersSize; i++ {
_, v := gControllers.GetByIndex(i)
output += ufmt.Sprintf("%s ", v.(std.Address))
}

output += "\n\n"
output += ufmt.Sprintf("Per request limit: %s\n\n", gLimit.String())

return output
}

func assertIsController() error {
caller := std.GetOrigCaller()
if caller != gControllerAddr {
return errors.New("restricted for controller")

ok := gControllers.Has(caller.String())
if !ok {
return errors.New(caller.String() + " is not on the controller list")
}
return nil
}
75 changes: 0 additions & 75 deletions examples/gno.land/r/gnoland/faucet/faucet_filetest.gno

This file was deleted.

90 changes: 72 additions & 18 deletions examples/gno.land/r/gnoland/faucet/faucet_test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -11,49 +11,103 @@ import (

func TestPackage(t *testing.T) {
var (
adminaddr = std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq")
controlleraddr = testutils.TestAddress("controller")
test1addr = testutils.TestAddress("test1")
adminaddr = std.Address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
faucetaddr = std.TestDerivePkgAddr("gno.land/r/faucet")
controlleraddr1 = testutils.TestAddress("controller1")
controlleraddr2 = testutils.TestAddress("controller2")
controlleraddr3 = testutils.TestAddress("controller3")
controlleraddr4 = testutils.TestAddress("controller4")
controlleraddr5 = testutils.TestAddress("controller5")
controlleraddr6 = testutils.TestAddress("controller6")
controlleraddr7 = testutils.TestAddress("controller7")
controlleraddr8 = testutils.TestAddress("controller8")
controlleraddr9 = testutils.TestAddress("controller9")
controlleraddr10 = testutils.TestAddress("controller10")
controlleraddr11 = testutils.TestAddress("controller11")

test1addr = testutils.TestAddress("test1")
)
// deposit 1000gnot to faucet contract

std.TestIssueCoins(faucetaddr, std.Coins{{"ugnot", 1000000000}})
std.TestSetOrigPkgAddr(faucetaddr)
assertBalance(t, faucetaddr, 1000000000)

// by default, balance is empty, and as a user I cannot call Transfer, or Admin commands.
std.TestSetOrigSend(std.Coins{{"ugnot", 2000000000}}, nil)

assertBalance(t, test1addr, 0)
assertErr(t, faucet.Transfer(test1addr))
assertErr(t, faucet.AdminSetControllerAddr(controlleraddr))
std.TestSetOrigCaller(controlleraddr)
assertErr(t, faucet.Transfer(test1addr))
std.TestSetOrigCaller(test1addr)
assertErr(t, faucet.Transfer(test1addr, 1000000))

assertErr(t, faucet.AdminAddController(controlleraddr1))
std.TestSetOrigCaller(controlleraddr1)
assertErr(t, faucet.Transfer(test1addr, 1000000))

// as an admin, set the controller to controlleraddr.
// as an admin, add the controller to contract and deposit more 2000gnot to contract
std.TestSetOrigCaller(adminaddr)
assertNoErr(t, faucet.AdminSetControllerAddr(controlleraddr))
assertNoErr(t, faucet.AdminAddController(controlleraddr1))
assertBalance(t, faucetaddr, 1000000000)

// now, send some tokens as controller.
std.TestSetOrigCaller(controlleraddr)
assertNoErr(t, faucet.Transfer(test1addr))
std.TestSetOrigCaller(controlleraddr1)
assertNoErr(t, faucet.Transfer(test1addr, 1000000))
assertBalance(t, test1addr, 1000000)
assertNoErr(t, faucet.Transfer(test1addr))
assertNoErr(t, faucet.Transfer(test1addr, 1000000))
assertBalance(t, test1addr, 2000000)
assertBalance(t, faucetaddr, 998000000)

// remove controller
// as an admin, remove controller
std.TestSetOrigCaller(adminaddr)
assertNoErr(t, faucet.AdminRemoveController(controlleraddr1))
std.TestSetOrigCaller(controlleraddr1)
assertErr(t, faucet.Transfer(test1addr, 1000000))

// duplicate controller
std.TestSetOrigCaller(adminaddr)
assertNoErr(t, faucet.AdminAddController(controlleraddr1))
assertErr(t, faucet.AdminAddController(controlleraddr1))
// add more than more than allowed controllers
assertNoErr(t, faucet.AdminAddController(controlleraddr2))
assertNoErr(t, faucet.AdminAddController(controlleraddr3))
assertNoErr(t, faucet.AdminAddController(controlleraddr4))
assertNoErr(t, faucet.AdminAddController(controlleraddr5))
assertNoErr(t, faucet.AdminAddController(controlleraddr6))
assertNoErr(t, faucet.AdminAddController(controlleraddr7))
assertNoErr(t, faucet.AdminAddController(controlleraddr8))
assertNoErr(t, faucet.AdminAddController(controlleraddr9))
assertNoErr(t, faucet.AdminAddController(controlleraddr10))
assertErr(t, faucet.AdminAddController(controlleraddr11))

// send more than per transfer limit
std.TestSetOrigCaller(adminaddr)
faucet.AdminSetTransferLimit(300000000)
std.TestSetOrigCaller(controlleraddr1)
assertErr(t, faucet.Transfer(test1addr, 301000000))

// block transefer from the address not on the controllers list.
std.TestSetOrigCaller(controlleraddr11)
assertErr(t, faucet.Transfer(test1addr, 1000000))
}

func assertErr(t *testing.T, err error) {
func assertErr(t *testing.T, err string) {
t.Helper()
if err == nil {

if err == "" {
t.Logf("info: got err: %v", err)
t.Errorf("expected an error, got nil.")
}
}

func assertNoErr(t *testing.T, err error) {
func assertNoErr(t *testing.T, err string) {
t.Helper()
if err != nil {
if err != "" {
t.Errorf("got err: %v.", err)
}
}

func assertBalance(t *testing.T, addr std.Address, expectedBal int64) {
t.Helper()

banker := std.GetBanker(std.BankerTypeReadonly)
coins := banker.GetCoins(addr)
got := coins.AmountOf("ugnot")
Expand Down

0 comments on commit bd598a5

Please sign in to comment.