PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/r/akkadia/beta/admin

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
admin
Namespace
akkadia / beta
Files
12 (gnomod.toml)
Exported functions
25
Module
gno.land/r/akkadia/beta/admin
gno
0.9

Files (12)

  • gnomod.tomltoml
  • admin.gnogno
  • fee_collector.gnogno
  • operator_faucet.gnogno
  • operator.gnogno
  • protocol.gnogno
  • render.gnogno
  • utils.gnogno
  • validation.gnogno
  • admin_test.gnogno
  • operator_faucet_test.gnogno
  • setup_test.gnogno
  • operator_faucet_test.gnogno
    1package admin23import (4	"testing"56	"chain"7	"chain/banker"8

    Functions

    • AcceptAdmin(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string})

    • CancelAdminTransfer(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string})

    • GetAdmin() string

    • GetExplorerURL() string

    • GetFaucetTargetAmount() int64

    • GetFeeCollector() string

    • GetOperators() [].uverse.address

    • GetPendingAdmin() string

    • GetProtocol() string

    • IsAdmin(address string) bool

    • IsFeeCollector(address string) bool

    • IsOperator(addr string) bool

    • IsProtocol(address string) bool

    • Render(path string) string

    • RequestFaucet(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}) int64

    • RequestFaucetFor(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, operator string) int64

    • RequestFaucets(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}) int64

    • SetExplorerURL(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, url string)

    • SetFaucetTargetAmount(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, amount int64)

    • SetFeeCollector(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, addr string)

    • SetOperator(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, addr string)

    • SetProtocol(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, addr string)

    • TransferAdmin(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, newAdmin string)

    • UnsetOperator(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, addr string)

    • Withdraw(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, recipient string, amount int64) int64

    Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

    Rendered

    RenderedRawgnoweb ↗

    vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.

    "chain/runtime"
    9
    10 "gno.land/p/nt/uassert/v0"
    11)
    12
    13const (
    14 testFaucetFundAmount int64 = 1000000
    15)
    16
    17type faucetTestHelper struct{}
    18
    19var faucetTest = &faucetTestHelper{}
    20
    21func TestSetFaucetTargetAmount(cur realm, t *testing.T) {
    22 tests := []struct {
    23 name string
    24 originCaller address
    25 realm runtime.Realm
    26 amount int64
    27 shouldPanic bool
    28 panicMsg string
    29 }{
    30 {"admin sets target amount", testAdmin, testing.NewUserRealm(testAdmin), 1000000, false, ""},
    31 {"unauthorized", unauthorizedUser, testing.NewUserRealm(unauthorizedUser), 1000000, true, "admin access required"},
    32 {"zero amount", testAdmin, testing.NewUserRealm(testAdmin), 0, true, "faucet target amount must be positive"},
    33 {"negative amount", testAdmin, testing.NewUserRealm(testAdmin), -1, true, "faucet target amount must be positive"},
    34 }
    35
    36 for _, tt := range tests {
    37 setupCommonAdminTests(cur, t)
    38 testing.SetOriginCaller(tt.originCaller)
    39 testing.SetRealm(tt.realm)
    40
    41 if tt.shouldPanic {
    42 uassert.AbortsWithMessage(t, cur, tt.panicMsg, func() {
    43 SetFaucetTargetAmount(cross(cur), tt.amount)
    44 })
    45 uassert.Equal(t, int64(0), GetFaucetTargetAmount())
    46 continue
    47 }
    48
    49 SetFaucetTargetAmount(cross(cur), tt.amount)
    50 uassert.Equal(t, tt.amount, GetFaucetTargetAmount())
    51 }
    52}
    53
    54func TestRequestFaucetTransfersDeficit(cur realm, t *testing.T) {
    55 setupCommonAdminTests(cur, t)
    56
    57 adminRealm := adminRealmAddr()
    58 adminBefore := adminUgnotBalance(adminRealm)
    59 operatorBefore := adminUgnotBalance(testOperator)
    60 expectedTransfer := int64(300000)
    61 faucetTest.FundAdmin(testFaucetFundAmount)
    62
    63 testing.SetOriginCaller(testAdmin)
    64 testing.SetRealm(testing.NewUserRealm(testAdmin))
    65 SetOperator(cross(cur), testOperator)
    66 SetFaucetTargetAmount(cross(cur), operatorBefore+expectedTransfer)
    67
    68 testing.SetOriginCaller(testOperator)
    69 testing.SetRealm(testing.NewUserRealm(testOperator))
    70 transferred := RequestFaucet(cross(cur))
    71
    72 uassert.Equal(t, expectedTransfer, transferred)
    73 uassert.Equal(t, operatorBefore+expectedTransfer, adminUgnotBalance(testOperator))
    74 uassert.Equal(t, adminBefore+testFaucetFundAmount-expectedTransfer, adminUgnotBalance(adminRealm))
    75}
    76
    77func TestRequestFaucetForTransfersDeficit(cur realm, t *testing.T) {
    78 setupCommonAdminTests(cur, t)
    79
    80 adminRealm := adminRealmAddr()
    81 adminBefore := adminUgnotBalance(adminRealm)
    82 operatorBefore := adminUgnotBalance(testOperator)
    83 expectedTransfer := int64(300000)
    84 faucetTest.FundAdmin(testFaucetFundAmount)
    85
    86 testing.SetOriginCaller(testAdmin)
    87 testing.SetRealm(testing.NewUserRealm(testAdmin))
    88 SetOperator(cross(cur), testOperator)
    89 SetFaucetTargetAmount(cross(cur), operatorBefore+expectedTransfer)
    90 transferred := RequestFaucetFor(cross(cur), testOperator)
    91
    92 uassert.Equal(t, expectedTransfer, transferred)
    93 uassert.Equal(t, operatorBefore+expectedTransfer, adminUgnotBalance(testOperator))
    94 uassert.Equal(t, adminBefore+testFaucetFundAmount-expectedTransfer, adminUgnotBalance(adminRealm))
    95}
    96
    97func TestRequestFaucetsTransfersDeficits(cur realm, t *testing.T) {
    98 setupCommonAdminTests(cur, t)
    99
    100 testing.SetOriginCaller(testAdmin)
    101 testing.SetRealm(testing.NewUserRealm(testAdmin))
    102 UnsetOperator(cross(cur), testAdmin)
    103 SetOperator(cross(cur), testOperator)
    104 SetOperator(cross(cur), testUser)
    105 SetOperator(cross(cur), testUser2)
    106
    107 adminRealm := adminRealmAddr()
    108 adminBefore := adminUgnotBalance(adminRealm)
    109 operatorBefore := adminUgnotBalance(testOperator)
    110 userBefore := adminUgnotBalance(testUser)
    111 user2Before := adminUgnotBalance(testUser2)
    112 targetAmount := maxInt64(operatorBefore, maxInt64(userBefore, user2Before)) + 300000
    113 if user2Before < targetAmount {
    114 faucetTest.Issue(testUser2, targetAmount-user2Before)
    115 user2Before = targetAmount
    116 }
    117 operatorDeficit := targetAmount - operatorBefore
    118 userDeficit := targetAmount - userBefore
    119 expectedTransfer := operatorDeficit + userDeficit
    120 faucetTest.FundAdmin(expectedTransfer)
    121
    122 testing.SetOriginCaller(testAdmin)
    123 testing.SetRealm(testing.NewUserRealm(testAdmin))
    124 SetFaucetTargetAmount(cross(cur), targetAmount)
    125 transferred := RequestFaucets(cross(cur))
    126
    127 uassert.Equal(t, expectedTransfer, transferred)
    128 uassert.Equal(t, targetAmount, adminUgnotBalance(testOperator))
    129 uassert.Equal(t, targetAmount, adminUgnotBalance(testUser))
    130 uassert.Equal(t, user2Before, adminUgnotBalance(testUser2))
    131 uassert.Equal(t, adminBefore, adminUgnotBalance(adminRealm))
    132}
    133
    134func TestRequestFaucetsReturnsZeroWithoutDeficits(cur realm, t *testing.T) {
    135 setupCommonAdminTests(cur, t)
    136
    137 testing.SetOriginCaller(testAdmin)
    138 testing.SetRealm(testing.NewUserRealm(testAdmin))
    139 UnsetOperator(cross(cur), testAdmin)
    140 SetOperator(cross(cur), testOperator)
    141 SetOperator(cross(cur), testUser)
    142
    143 operatorBefore := adminUgnotBalance(testOperator)
    144 userBefore := adminUgnotBalance(testUser)
    145 targetAmount := maxInt64(operatorBefore, userBefore)
    146 if operatorBefore < targetAmount {
    147 faucetTest.Issue(testOperator, targetAmount-operatorBefore)
    148 }
    149 if userBefore < targetAmount {
    150 faucetTest.Issue(testUser, targetAmount-userBefore)
    151 }
    152 if targetAmount <= 0 {
    153 targetAmount = 1
    154 faucetTest.Issue(testOperator, targetAmount)
    155 faucetTest.Issue(testUser, targetAmount)
    156 }
    157
    158 adminBefore := adminUgnotBalance(adminRealmAddr())
    159 testing.SetOriginCaller(testAdmin)
    160 testing.SetRealm(testing.NewUserRealm(testAdmin))
    161 SetFaucetTargetAmount(cross(cur), targetAmount)
    162 transferred := RequestFaucets(cross(cur))
    163
    164 uassert.Equal(t, int64(0), transferred)
    165 uassert.Equal(t, adminBefore, adminUgnotBalance(adminRealmAddr()))
    166}
    167
    168func TestRequestFaucetRejectsInvalidRequest(cur realm, t *testing.T) {
    169 tests := []struct {
    170 name string
    171 setup func(cur realm) (address, runtime.Realm)
    172 panicMsg string
    173 }{
    174 {
    175 name: "non-operator direct caller",
    176 setup: func(cur realm) (address, runtime.Realm) {
    177 testing.SetOriginCaller(testAdmin)
    178 testing.SetRealm(testing.NewUserRealm(testAdmin))
    179 SetFaucetTargetAmount(cross(cur), 1000000)
    180 faucetTest.FundAdmin(testFaucetFundAmount)
    181 return unauthorizedUser, testing.NewUserRealm(unauthorizedUser)
    182 },
    183 panicMsg: "operator access required",
    184 },
    185 {
    186 name: "operator balance already reaches target",
    187 setup: func(cur realm) (address, runtime.Realm) {
    188 operatorBalance := adminUgnotBalance(testOperator)
    189 if operatorBalance == 0 {
    190 faucetTest.Issue(testOperator, 1)
    191 operatorBalance = 1
    192 }
    193 testing.SetOriginCaller(testAdmin)
    194 testing.SetRealm(testing.NewUserRealm(testAdmin))
    195 SetOperator(cross(cur), testOperator)
    196 SetFaucetTargetAmount(cross(cur), operatorBalance)
    197 faucetTest.FundAdmin(testFaucetFundAmount)
    198 return testOperator, testing.NewUserRealm(testOperator)
    199 },
    200 panicMsg: "operator balance is not below faucet target",
    201 },
    202 {
    203 name: "admin realm balance is insufficient",
    204 setup: func(cur realm) (address, runtime.Realm) {
    205 adminBalance := adminUgnotBalance(adminRealmAddr())
    206 testing.SetOriginCaller(testAdmin)
    207 testing.SetRealm(testing.NewUserRealm(testAdmin))
    208 SetOperator(cross(cur), testOperator)
    209 SetFaucetTargetAmount(cross(cur), adminUgnotBalance(testOperator)+adminBalance+1)
    210 return testOperator, testing.NewUserRealm(testOperator)
    211 },
    212 panicMsg: "admin realm balance is insufficient",
    213 },
    214 {
    215 name: "operator origin through code realm",
    216 setup: func(cur realm) (address, runtime.Realm) {
    217 testing.SetOriginCaller(testAdmin)
    218 testing.SetRealm(testing.NewUserRealm(testAdmin))
    219 SetOperator(cross(cur), testOperator)
    220 SetFaucetTargetAmount(cross(cur), adminUgnotBalance(testOperator)+1)
    221 faucetTest.FundAdmin(testFaucetFundAmount)
    222 return testOperator, testing.NewCodeRealm("gno.land/r/akkadia/beta/operator_faucet_relay")
    223 },
    224 panicMsg: "contract calls not allowed: function must be called directly by user",
    225 },
    226 {
    227 name: "target amount is not configured",
    228 setup: func(cur realm) (address, runtime.Realm) {
    229 testing.SetOriginCaller(testAdmin)
    230 testing.SetRealm(testing.NewUserRealm(testAdmin))
    231 SetOperator(cross(cur), testOperator)
    232 faucetTest.FundAdmin(testFaucetFundAmount)
    233 return testOperator, testing.NewUserRealm(testOperator)
    234 },
    235 panicMsg: "faucet target amount must be positive",
    236 },
    237 }
    238
    239 for _, tt := range tests {
    240 setupCommonAdminTests(cur, t)
    241 caller, rlm := tt.setup(cur)
    242 testing.SetOriginCaller(caller)
    243 testing.SetRealm(rlm)
    244
    245 uassert.AbortsWithMessage(t, cur, tt.panicMsg, func() {
    246 RequestFaucet(cross(cur))
    247 })
    248 }
    249}
    250
    251func TestRequestFaucetForRejectsInvalidRequest(cur realm, t *testing.T) {
    252 tests := []struct {
    253 name string
    254 setup func(cur realm) (address, runtime.Realm, address)
    255 panicMsg string
    256 }{
    257 {
    258 name: "non-admin caller",
    259 setup: func(cur realm) (address, runtime.Realm, address) {
    260 testing.SetOriginCaller(testAdmin)
    261 testing.SetRealm(testing.NewUserRealm(testAdmin))
    262 SetOperator(cross(cur), testOperator)
    263 SetFaucetTargetAmount(cross(cur), 1000000)
    264 faucetTest.FundAdmin(testFaucetFundAmount)
    265 return unauthorizedUser, testing.NewUserRealm(unauthorizedUser), testOperator
    266 },
    267 panicMsg: "admin access required",
    268 },
    269 {
    270 name: "non-operator target",
    271 setup: func(cur realm) (address, runtime.Realm, address) {
    272 testing.SetOriginCaller(testAdmin)
    273 testing.SetRealm(testing.NewUserRealm(testAdmin))
    274 SetFaucetTargetAmount(cross(cur), 1000000)
    275 faucetTest.FundAdmin(testFaucetFundAmount)
    276 return testAdmin, testing.NewUserRealm(testAdmin), unauthorizedUser
    277 },
    278 panicMsg: "operator access required",
    279 },
    280 {
    281 name: "operator balance already reaches target",
    282 setup: func(cur realm) (address, runtime.Realm, address) {
    283 operatorBalance := adminUgnotBalance(testOperator)
    284 if operatorBalance == 0 {
    285 faucetTest.Issue(testOperator, 1)
    286 operatorBalance = 1
    287 }
    288 testing.SetOriginCaller(testAdmin)
    289 testing.SetRealm(testing.NewUserRealm(testAdmin))
    290 SetOperator(cross(cur), testOperator)
    291 SetFaucetTargetAmount(cross(cur), operatorBalance)
    292 faucetTest.FundAdmin(testFaucetFundAmount)
    293 return testAdmin, testing.NewUserRealm(testAdmin), testOperator
    294 },
    295 panicMsg: "operator balance is not below faucet target",
    296 },
    297 {
    298 name: "admin realm balance is insufficient",
    299 setup: func(cur realm) (address, runtime.Realm, address) {
    300 adminBalance := adminUgnotBalance(adminRealmAddr())
    301 testing.SetOriginCaller(testAdmin)
    302 testing.SetRealm(testing.NewUserRealm(testAdmin))
    303 SetOperator(cross(cur), testOperator)
    304 SetFaucetTargetAmount(cross(cur), adminUgnotBalance(testOperator)+adminBalance+1)
    305 return testAdmin, testing.NewUserRealm(testAdmin), testOperator
    306 },
    307 panicMsg: "admin realm balance is insufficient",
    308 },
    309 {
    310 name: "target amount is not configured",
    311 setup: func(cur realm) (address, runtime.Realm, address) {
    312 testing.SetOriginCaller(testAdmin)
    313 testing.SetRealm(testing.NewUserRealm(testAdmin))
    314 SetOperator(cross(cur), testOperator)
    315 faucetTest.FundAdmin(testFaucetFundAmount)
    316 return testAdmin, testing.NewUserRealm(testAdmin), testOperator
    317 },
    318 panicMsg: "faucet target amount must be positive",
    319 },
    320 }
    321
    322 for _, tt := range tests {
    323 setupCommonAdminTests(cur, t)
    324 caller, rlm, operator := tt.setup(cur)
    325 testing.SetOriginCaller(caller)
    326 testing.SetRealm(rlm)
    327
    328 uassert.AbortsWithMessage(t, cur, tt.panicMsg, func() {
    329 RequestFaucetFor(cross(cur), operator)
    330 })
    331 }
    332}
    333
    334func TestRequestFaucetsRejectsInvalidRequest(cur realm, t *testing.T) {
    335 tests := []struct {
    336 name string
    337 setup func(cur realm) (address, runtime.Realm)
    338 panicMsg string
    339 }{
    340 {
    341 name: "non-admin caller",
    342 setup: func(cur realm) (address, runtime.Realm) {
    343 testing.SetOriginCaller(testAdmin)
    344 testing.SetRealm(testing.NewUserRealm(testAdmin))
    345 SetOperator(cross(cur), testOperator)
    346 SetFaucetTargetAmount(cross(cur), adminUgnotBalance(testOperator)+1)
    347 faucetTest.FundAdmin(testFaucetFundAmount)
    348 return unauthorizedUser, testing.NewUserRealm(unauthorizedUser)
    349 },
    350 panicMsg: "admin access required",
    351 },
    352 {
    353 name: "admin realm balance is insufficient",
    354 setup: func(cur realm) (address, runtime.Realm) {
    355 adminBalance := adminUgnotBalance(adminRealmAddr())
    356 testing.SetOriginCaller(testAdmin)
    357 testing.SetRealm(testing.NewUserRealm(testAdmin))
    358 SetOperator(cross(cur), testOperator)
    359 SetFaucetTargetAmount(cross(cur), adminUgnotBalance(testOperator)+adminBalance+1)
    360 return testAdmin, testing.NewUserRealm(testAdmin)
    361 },
    362 panicMsg: "admin realm balance is insufficient",
    363 },
    364 {
    365 name: "target amount is not configured",
    366 setup: func(cur realm) (address, runtime.Realm) {
    367 testing.SetOriginCaller(testAdmin)
    368 testing.SetRealm(testing.NewUserRealm(testAdmin))
    369 SetOperator(cross(cur), testOperator)
    370 faucetTest.FundAdmin(testFaucetFundAmount)
    371 return testAdmin, testing.NewUserRealm(testAdmin)
    372 },
    373 panicMsg: "faucet target amount must be positive",
    374 },
    375 }
    376
    377 for _, tt := range tests {
    378 setupCommonAdminTests(cur, t)
    379 caller, rlm := tt.setup(cur)
    380 testing.SetOriginCaller(caller)
    381 testing.SetRealm(rlm)
    382
    383 uassert.AbortsWithMessage(t, cur, tt.panicMsg, func() {
    384 RequestFaucets(cross(cur))
    385 })
    386 }
    387}
    388
    389func TestWithdrawTransfersAdminRealmBalance(cur realm, t *testing.T) {
    390 setupCommonAdminTests(cur, t)
    391
    392 adminRealm := adminRealmAddr()
    393 adminBefore := adminUgnotBalance(adminRealm)
    394 recipientBefore := adminUgnotBalance(testUser)
    395 withdrawAmount := int64(200000)
    396 faucetTest.FundAdmin(withdrawAmount)
    397
    398 testing.SetOriginCaller(testAdmin)
    399 testing.SetRealm(testing.NewUserRealm(testAdmin))
    400 transferred := Withdraw(cross(cur), testUser, withdrawAmount)
    401
    402 uassert.Equal(t, withdrawAmount, transferred)
    403 uassert.Equal(t, recipientBefore+withdrawAmount, adminUgnotBalance(testUser))
    404 uassert.Equal(t, adminBefore, adminUgnotBalance(adminRealm))
    405}
    406
    407type withdrawRejectContext struct {
    408 caller address
    409 recipient address
    410 amount int64
    411 adminBefore int64
    412 recipientBefore int64
    413 checkRecipient bool
    414}
    415
    416func TestWithdrawRejectsInvalidRequest(cur realm, t *testing.T) {
    417 tests := []struct {
    418 name string
    419 setup func() withdrawRejectContext
    420 panicMsg string
    421 }{
    422 {
    423 name: "non-admin caller",
    424 setup: func() withdrawRejectContext {
    425 faucetTest.FundAdmin(1)
    426 return withdrawRejectContext{
    427 caller: unauthorizedUser,
    428 recipient: testUser,
    429 amount: 1,
    430 }
    431 },
    432 panicMsg: "admin access required",
    433 },
    434 {
    435 name: "invalid recipient",
    436 setup: func() withdrawRejectContext {
    437 faucetTest.FundAdmin(1)
    438 return withdrawRejectContext{
    439 caller: testAdmin,
    440 recipient: address(""),
    441 amount: 1,
    442 }
    443 },
    444 panicMsg: "invalid address",
    445 },
    446 {
    447 name: "zero amount",
    448 setup: func() withdrawRejectContext {
    449 faucetTest.FundAdmin(1)
    450 return withdrawRejectContext{
    451 caller: testAdmin,
    452 recipient: testUser,
    453 amount: 0,
    454 }
    455 },
    456 panicMsg: "amount must be greater than 0",
    457 },
    458 {
    459 name: "negative amount",
    460 setup: func() withdrawRejectContext {
    461 faucetTest.FundAdmin(1)
    462 return withdrawRejectContext{
    463 caller: testAdmin,
    464 recipient: testUser,
    465 amount: -1,
    466 }
    467 },
    468 panicMsg: "amount must be greater than 0",
    469 },
    470 {
    471 name: "admin realm balance is insufficient",
    472 setup: func() withdrawRejectContext {
    473 return withdrawRejectContext{
    474 caller: testAdmin,
    475 recipient: testUser,
    476 amount: adminUgnotBalance(adminRealmAddr()) + 1,
    477 }
    478 },
    479 panicMsg: "admin realm balance is insufficient",
    480 },
    481 }
    482
    483 for _, tt := range tests {
    484 setupCommonAdminTests(cur, t)
    485 ctx := tt.setup()
    486 ctx.adminBefore = adminUgnotBalance(adminRealmAddr())
    487 ctx.checkRecipient = ctx.recipient.IsValid()
    488 if ctx.checkRecipient {
    489 ctx.recipientBefore = adminUgnotBalance(ctx.recipient)
    490 }
    491 testing.SetOriginCaller(ctx.caller)
    492 testing.SetRealm(testing.NewUserRealm(ctx.caller))
    493
    494 uassert.AbortsWithMessage(t, cur, tt.panicMsg, func() {
    495 Withdraw(cross(cur), ctx.recipient, ctx.amount)
    496 })
    497 uassert.Equal(t, ctx.adminBefore, adminUgnotBalance(adminRealmAddr()))
    498 if ctx.checkRecipient {
    499 uassert.Equal(t, ctx.recipientBefore, adminUgnotBalance(ctx.recipient))
    500 }
    501 }
    502}
    503
    504func adminUgnotBalance(addr address) int64 {
    505 bnk := banker.NewReadonlyBanker()
    506 return bnk.GetCoins(addr).AmountOf("ugnot")
    507}
    508
    509func (h *faucetTestHelper) FundAdmin(amount int64) {
    510 h.Issue(adminRealmAddr(), amount)
    511}
    512
    513func (h *faucetTestHelper) Issue(addr address, amount int64) {
    514 if amount <= 0 {
    515 return
    516 }
    517 testing.IssueCoins(addr, chain.Coins{{"ugnot", amount}})
    518}
    519
    520func maxInt64(a int64, b int64) int64 {
    521 if a > b {
    522 return a
    523 }
    524 return b
    525}
    526