Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

GSW-1968 refactor: integration common and position contract #447

Merged
merged 5 commits into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions _deploy/r/gnoswap/common/access.gno
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const (
ErrNoPermission = "caller(%s) has no permission"
)

// AssertCaller checks if the caller is the given address.
func AssertCaller(caller, addr std.Address) error {
if caller != addr {
return ufmt.Errorf(ErrNoPermission, caller.String())
Expand All @@ -25,55 +26,63 @@ func SatisfyCond(cond bool) error {
return nil
}

// AdminOnly checks if the caller is the admin.
func AdminOnly(caller std.Address) error {
if caller != consts.ADMIN {
return ufmt.Errorf(ErrNoPermission, caller.String())
}
return nil
}

// GovernanceOnly checks if the caller is the gov governance contract.
func GovernanceOnly(caller std.Address) error {
if caller != consts.GOV_GOVERNANCE_ADDR {
return ufmt.Errorf(ErrNoPermission, caller.String())
}
return nil
}

// GovStakerOnly checks if the caller is the gov staker contract.
func GovStakerOnly(caller std.Address) error {
if caller != consts.GOV_STAKER_ADDR {
return ufmt.Errorf(ErrNoPermission, caller.String())
}
return nil
}

// RouterOnly checks if the caller is the router contract.
func RouterOnly(caller std.Address) error {
if caller != consts.ROUTER_ADDR {
return ufmt.Errorf(ErrNoPermission, caller.String())
}
return nil
}

// PositionOnly checks if the caller is the position contract.
func PositionOnly(caller std.Address) error {
if caller != consts.POSITION_ADDR {
return ufmt.Errorf(ErrNoPermission, caller.String())
}
return nil
}

// StakerOnly checks if the caller is the staker contract.
func StakerOnly(caller std.Address) error {
if caller != consts.STAKER_ADDR {
return ufmt.Errorf(ErrNoPermission, caller.String())
}
return nil
}

// LaunchpadOnly checks if the caller is the launchpad contract.
func LaunchpadOnly(caller std.Address) error {
if caller != consts.LAUNCHPAD_ADDR {
return ufmt.Errorf(ErrNoPermission, caller.String())
}
return nil
}

// EmissionOnly checks if the caller is the emission contract.
func EmissionOnly(caller std.Address) error {
if caller != consts.EMISSION_ADDR {
return ufmt.Errorf(ErrNoPermission, caller.String())
Expand All @@ -90,8 +99,7 @@ func TokenRegisterOnly(caller std.Address) error {
return nil
}

// realm assertion

// UserOnly checks if the caller is a user.
func UserOnly(prev std.Realm) error {
if !prev.IsUser() {
return ufmt.Errorf("caller(%s) is not a user", prev.PkgPath())
Expand Down
2 changes: 1 addition & 1 deletion _deploy/r/gnoswap/common/address_and_username.gno
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ func UserToAddr(user pusers.AddressOrName) std.Address {
// It panics with a detailed error message if the address is invalid.
func assertValidAddr(addr std.Address) {
if !addr.IsValid() {
panic(addDetailToError(errInvalidAddr, addr.String()))
panic(newErrorWithDetail(errInvalidAddr, addr.String()))
}
}
16 changes: 13 additions & 3 deletions _deploy/r/gnoswap/common/errors.gno
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,19 @@ var (
errInvalidAddr = errors.New("[GNOSWAP-COMMON-005] invalid address")
errOverflow = errors.New("[GNOSWAP-COMMON-006] overflow")
errInvalidTokenId = errors.New("[GNOSWAP-COMMON-007] invalid tokenId")
errInvalidInput = errors.New("[GNOSWAP-COMMON-008] invalid input data")
errOverFlow = errors.New("[GNOSWAP-COMMON-009] overflow")
errIdenticalTicks = errors.New("[GNOSWAP-COMMON-010] identical ticks")
)

func addDetailToError(err error, detail string) string {
finalErr := ufmt.Errorf("%s || %s", err.Error(), detail)
return finalErr.Error()
// newErrorWithDetail appends additional context or details to an existing error message.
//
// Parameters:
// - err: The original error (error).
// - detail: Additional context or detail to append to the error message (string).
//
// Returns:
// - string: The combined error message in the format "<original_error> || <detail>".
func newErrorWithDetail(err error, detail string) string {
return ufmt.Errorf("%s || %s", err.Error(), detail).Error()
}
2 changes: 1 addition & 1 deletion _deploy/r/gnoswap/common/grc20reg_helper.gno
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func IsRegistered(path string) error {
// if token is not registered, it will panic
func MustRegistered(path string) {
if err := IsRegistered(path); err != nil {
panic(addDetailToError(
panic(newErrorWithDetail(
errNotRegistered,
ufmt.Sprintf("token(%s)", path),
))
Expand Down
4 changes: 2 additions & 2 deletions _deploy/r/gnoswap/common/grc721_token_id.gno
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
// output: grc721.TokenID
func TokenIdFrom(tokenId interface{}) grc721.TokenID {
if tokenId == nil {
panic(addDetailToError(
panic(newErrorWithDetail(
errInvalidTokenId,
"can not be nil",
))
Expand All @@ -33,7 +33,7 @@ func TokenIdFrom(tokenId interface{}) grc721.TokenID {
return tokenId.(grc721.TokenID)
default:
estimatedType := ufmt.Sprintf("%T", tokenId)
panic(addDetailToError(
panic(newErrorWithDetail(
errInvalidTokenId,
ufmt.Sprintf("unsupported tokenId type: %s", estimatedType),
))
Expand Down
104 changes: 51 additions & 53 deletions _deploy/r/gnoswap/common/halt.gno
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,49 @@ import (
"std"

"gno.land/p/demo/ufmt"

"gno.land/r/gnoswap/v1/consts"
)

var (
halted bool = false
)
// halted is a global flag that indicates whether the GnoSwap is currently halted.
// When true, most operations are disabled to prevent further actions.
// Default value is false, meaning the GnoSwap is active by default.
var halted bool = false

// GetHalt returns the current halted status of the GnoSwap.
//
// Returns:
// - bool: true if the GnoSwap is halted, false otherwise.
func GetHalt() bool {
return halted
}

// IsHalted checks if the GnoSwap is currently halted.
// If the GnoSwap is halted, the function panics with an errHalted error.
//
// Panics:
// - If the halted flag is true, indicating that the GnoSwap is inactive.
func IsHalted() {
if halted {
panic(addDetailToError(
panic(newErrorWithDetail(
errHalted,
"gnoswap halted",
"GnoSwap is halted",
))
}
}

// SetHaltByAdmin sets the halt status.
// SetHaltByAdmin allows an admin to set the halt status of the GnoSwap.
// Only an admin can execute this function. If a non-admin attempts to call this function,
// the function panics with an errNoPermission error.
//
// Parameters:
// - halt (bool): The new halt status to set (true to halt, false to unhalt).
//
// Panics:
// - If the caller is not an admin, the function will panic with an errNoPermission error.
func SetHaltByAdmin(halt bool) {
caller := std.PrevRealm().Addr()
err := AdminOnly(caller)
if err != nil {
panic(addDetailToError(
caller := getPrevAddr()
if err := AdminOnly(caller); err != nil {
panic(newErrorWithDetail(
errNoPermission,
ufmt.Sprintf(
"only admin(%s) can set halt, called from %s",
Expand All @@ -39,34 +55,21 @@ func SetHaltByAdmin(halt bool) {
),
))
}

setHalt(halt)

prevAddr, prevRealm := getPrev()
if halt {
std.Emit(
"SetHaltByAdmin",
"prevAddr", prevAddr,
"prevRealm", prevRealm,
"halt", ufmt.Sprintf("%t", halt),
)
} else {
std.Emit(
"UnsetHaltByAdmin",
"prevAddr", prevAddr,
"prevRealm", prevRealm,
"halt", ufmt.Sprintf("%t", halt),
)
}
}

// SetHalt sets the halt status.
// Only governance contract can execute this function via proposal
// SetHalt allows the governance contract to set the halt status of the GnoSwap.
// Only the governance contract can execute this function through a proposal process.
//
// Parameters:
// - halt (bool): The new halt status to set (true to halt, false to unhalt).
//
// Panics:
// - If the caller is not the governance contract, the function will panic with an errNoPermission error.
func SetHalt(halt bool) {
caller := std.PrevRealm().Addr()
err := GovernanceOnly(caller)
if err != nil {
panic(addDetailToError(
caller := getPrevAddr()
if err := GovernanceOnly(caller); err != nil {
panic(newErrorWithDetail(
errNoPermission,
ufmt.Sprintf(
"only governance(%s) can set halt, called from %s",
Expand All @@ -75,27 +78,22 @@ func SetHalt(halt bool) {
),
))
}

setHalt(halt)

prevAddr, prevRealm := getPrev()
if halt {
std.Emit(
"SetHalt",
"prevAddr", prevAddr,
"prevRealm", prevRealm,
"halt", ufmt.Sprintf("%t", halt),
)
} else {
std.Emit(
"UnsetHalt",
"prevAddr", prevAddr,
"prevRealm", prevRealm,
"halt", ufmt.Sprintf("%t", halt),
)
}
}

// setHalt updates the halted flag to the specified value.
// This is an internal function that should only be called by SetHalt or SetHaltByAdmin.
//
// Parameters:
// - halt (bool): The new halt status to set.
func setHalt(halt bool) {
halted = halt

prevAddr, prevRealm := getPrevAsString()
std.Emit(
"setHalt",
"prevAddr", prevAddr,
"prevRealm", prevRealm,
"halt", ufmt.Sprintf("%t", halt),
)
}
44 changes: 34 additions & 10 deletions _deploy/r/gnoswap/common/limit_caller.gno
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,49 @@ import (
"std"

"gno.land/p/demo/ufmt"

"gno.land/r/gnoswap/v1/consts"
)

var (
limitCaller bool = true
)
// limitCaller is a global boolean flag that controls whether function calls are restricted.
// Default value is true, meaning call restrictions are enabled by default.
var limitCaller bool = true

// GetLimitCaller returns the current state of the limitCaller flag.
// If true, call restrictions are active; if false, call restrictions are disabled.
//
// Returns:
// - bool: Current state of the limitCaller (true if active, false if inactive).
func GetLimitCaller() bool {
return limitCaller
}

// SetLimitCaller updates the limitCaller flag to either enable or disable call restrictions.
// This function can only be called by an admin. If a non-admin attempts to call this function,
// the function will panic.
//
// Parameters:
// - v (bool): The new state for the limitCaller flag (true to enable, false to disable).
//
// Panics:
// - If the caller is not an admin, the function panics with an errNoPermission error.
func SetLimitCaller(v bool) {
caller := std.PrevRealm().Addr()
if caller != consts.ADMIN {
panic(addDetailToError(
caller := getPrevAddr()
if err := AdminOnly(caller); err != nil {
panic(newErrorWithDetail(
errNoPermission,
ufmt.Sprintf("limit_caller.gno__SetLimitCaller() || only admin(%s) can set limit caller, called from %s", consts.ADMIN, caller),
))
ufmt.Sprintf(
"only Admin can set halt, called from %s",
caller,
)),
)
}

limitCaller = v

prevAddr, prevPkgPath := getPrevAsString()
std.Emit(
"SetLimitCaller",
"prevAddr", prevAddr,
"prevRealm", prevPkgPath,
"limitCaller", ufmt.Sprintf("%t", v),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,23 @@ import (
"testing"

"gno.land/p/demo/uassert"

"gno.land/r/gnoswap/v1/consts"
)

var adminRealm = std.NewUserRealm(consts.ADMIN)

func TestSetLimitCaller(t *testing.T) {
t.Run("initial check", func(t *testing.T) {
uassert.True(t, GetLimitCaller())
})

t.Run("with non-admin privilege, panics", func(t *testing.T) {
uassert.PanicsWithMessage(t,
`[GNOSWAP-COMMON-001] caller has no permission || limit_caller.gno__SetLimitCaller() || only admin(g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d) can set limit caller, called from g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm`,
`[GNOSWAP-COMMON-001] caller has no permission || only Admin can set halt, called from g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm`,
func() { SetLimitCaller(false) },
)
})

t.Run("with admin privilege, success", func(t *testing.T) {
std.TestSetRealm(adminRealm)
std.TestSetRealm(std.NewUserRealm(consts.ADMIN))
SetLimitCaller(false)
uassert.False(t, GetLimitCaller())
})
Expand Down
Loading
Loading