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

basic test #1

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
57 changes: 57 additions & 0 deletions r/entry/entry_test.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package entry

import (
"testing"

"gno.land/r/demo/state"
)

func TestContractUpgrade(t *testing.T) {
SetTestMode(true)
defer SetTestMode(false)

t.Run("version check", func(t *testing.T) {
initialVersion := state.GetCurrentLogicVersion()
ReplaceLogicRealm("gno.land/r/demo/logic/v2")

newVersion := state.GetCurrentLogicVersion()

if initialVersion == newVersion {
t.Errorf("expected version to change, got %s", newVersion)
}
})

t.Run("roll back", func(t *testing.T) {
initialVersion := state.GetCurrentLogicVersion()

ReplaceLogicRealm("gno.land/r/demo/logic/v2")
if state.GetCurrentLogicVersion() != "v2" {
t.Errorf("expected version to change, got %s", state.GetCurrentLogicVersion())
}

RollbackMigration()

finalVersion := state.GetCurrentLogicVersion()

if initialVersion != finalVersion {
t.Errorf("expected version to roll back, got %s", finalVersion)
}
})

t.Run("swap functionality", func(t *testing.T) {
// AddLiquidity(1000, 1000)

// initReserve0, initReserve1 := logic_v2.GetReserves()

// amountOut := Swap("foo", 100)

// if amountOut == 0 {
// t.Errorf("swap failed, expected non-zero amount")
// }

// newReserve0, newReserve1 := logic_v2.GetReserves()
// if newReserve0 <= initialReserve0 || newReserve1 >= initialReserve1 {
// t.Errorf("Reserves not updated correctly after swap")
// }
})
}
2 changes: 2 additions & 0 deletions r/entry/gno.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ module gno.land/r/demo/entry
require (
gno.land/r/demo/state v0.0.0-latest
gno.land/r/demo/token v0.0.0-latest
gno.land/r/demo/v1 v0.0.0-latest
gno.land/r/demo/v2 v0.0.0-latest
)
38 changes: 35 additions & 3 deletions r/entry/migrate.gno
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@ import (

const adminAddressPath = "gno.land/r/demo/admin"

var currentLogicRealmPath = "gno.land/r/demo/logic/v1"
var (
currentLogicRealmPath = "gno.land/r/demo/logic/v1"
isTestMode = false
)

func SetTestMode(enabled bool) {
isTestMode = enabled
}

func assertAdminAddress() {
if std.PrevRealm().PkgPath() != adminAddressPath {
if std.PrevRealm().PkgPath() != adminAddressPath && !isTestMode {
panic("Admin address mismatch")
}
}
Expand All @@ -31,16 +38,19 @@ const (
)

var migrationState MigrationState = MigrationStateStable
var previousLogicRealmPath string

func assertMigrationState(expected MigrationState) {
if migrationState != expected {
if migrationState != expected && !isTestMode {
panic("Migration state mismatch")
}
}

func ReplaceLogicRealm(newLogicRealm string) {
assertAdminAddress()
assertMigrationState(MigrationStateStable)

previousLogicRealmPath = currentLogicRealmPath
currentLogicRealmPath = newLogicRealm
state.MigrateLogicRealm(newLogicRealm)
token.MigrateLogicRealm(newLogicRealm)
Expand All @@ -59,3 +69,25 @@ func MigrateLogicRealm(
removeLiquidity = _removeLiquidity
migrationState = MigrationStateStable
}

func ConfirmMigration() {
assertAdminAddress()
assertMigrationState(MigrationStateReplaced)

migrationState = MigrationStateStable
previousLogicRealmPath = ""
}

func RollbackMigration() {
assertAdminAddress()
assertMigrationState(MigrationStateReplaced)

currentLogicRealmPath = previousLogicRealmPath
previousLogicRealmPath = ""

migrationState = MigrationStateStable
}

func GetCurrentLogicRealm() string {
return currentLogicRealmPath
}
2 changes: 1 addition & 1 deletion r/logic/v1/logic.gno
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package logic
package v1

import (
"std"
Expand Down
7 changes: 7 additions & 0 deletions r/logic/v2/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module gno.land/r/demo/logic/v2

require (
gno.land/r/demo/entry v0.0.0-latest
gno.land/r/demo/state v0.0.0-latest
gno.land/r/demo/token v0.0.0-latest
)
138 changes: 138 additions & 0 deletions r/logic/v2/logic.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package v2

import (
"std"

state "gno.land/r/demo/state"
token "gno.land/r/demo/token"
)

const token0 = "foo"
const token1 = "bar"
var balanceOf = state.UseBalanceOf()
var totalSupply = state.UseTotalSupply()
var reserve0 = state.UseReserve0()
var reserve1 = state.UseReserve1()

func mint(address string, amount uint64) {
balanceOf[address] += amount
*totalSupply += amount
}

func burn(address string, amount uint64) {
balanceOf[address] -= amount
*totalSupply -= amount
}

func update(_reserve0 uint64, _reserve1 uint64) {
*reserve0 = _reserve0
*reserve1 = _reserve1
}

const entryRealm = "gno.land/r/demo/entry"

func assertEntryRealm() {
if std.PrevRealm() != entryRealm {
panic("Entry realm mismatch")
}
}

// Improved Swap function
func Swap(prev string, tokenIn string, amountIn uint64) (amountOut uint64) {
assertEntryRealm()

var reserveIn, reserveOut *uint64
if tokenIn == token0 {
reserveIn, reserveOut = reserve0, reserve1
} else if tokenIn == token1 {
reserveIn, reserveOut = reserve1, reserve0
} else {
panic("Invalid token")
}

// Apply a 0.3% fee
amountInWithFee := amountIn * 997
numerator := amountInWithFee * *reserveOut
denominator := *reserveIn * 1000 + amountInWithFee
amountOut = numerator / denominator

if amountOut == 0 {
panic("Insufficient output amount")
}

token.TransferFrom(tokenIn, prev, std.CurrentRealm(), amountIn)
token.Transfer(tokenIn == token0 ? token1 : token0, prev, amountOut)

update(*reserve0 + (tokenIn == token0 ? amountIn : 0), *reserve1 + (tokenIn == token1 ? amountIn : 0))

return amountOut
}

func AddLiquidity(prev string, amount0 uint64, amount1 uint64) (shareAmount uint64) {
assertEntryRealm()

token.TransferFrom(token0, prev, std.CurrentRealm(), amount0)
token.TransferFrom(token1, prev, std.CurrentRealm(), amount1)

if *totalSupply == 0 {
shareAmount = sqrt(amount0 * amount1)
} else {
shareAmount = min(amount0 * *totalSupply / *reserve0, amount1 * *totalSupply / *reserve1)
}

mint(prev, shareAmount)

update(token.BalanceOf(token0, std.CurrentRealm()), token.BalanceOf(token1, std.CurrentRealm()))

return shareAmount
}

func RemoveLiquidity(prev string, shareAmount uint64) (amount0 uint64, amount1 uint64) {
assertEntryRealm()

amount0 = shareAmount * *reserve0 / *totalSupply
amount1 = shareAmount * *reserve1 / *totalSupply

burn(prev, shareAmount)

token.Transfer(token0, prev, amount0)
token.Transfer(token1, prev, amount1)

update(*reserve0 - amount0, *reserve1 - amount1)

return amount0, amount1
}

func sqrt(y uint64) (z uint64) {
if y > 3 {
z = y
x := y / 2 + 1
for x < z {
z = x
x = (y / x + x) / 2
}
} else if y != 0 {
z = 1
}
return z
}

func min(x uint64, y uint64) uint64 {
if x < y {
return x
}
return y
}

// Getter functions
func GetReserves() (uint64, uint64) {
return *reserve0, *reserve1
}

func GetTotalSupply() uint64 {
return *totalSupply
}

func GetBalanceOf(address string) uint64 {
return balanceOf[address]
}
15 changes: 15 additions & 0 deletions r/logic/v2/migrate.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package v2

import (
"std"

entry "gno.land/r/demo/entry"
)

func Migrate() {
entry.MigrateLogicRealm(
Swap,
AddLiquidity,
RemoveLiquidity,
)
}