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

feat: improve realms code #2

Merged
merged 8 commits into from
Oct 12, 2024
1 change: 1 addition & 0 deletions contracts/type.gno
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ type Vault struct {
token0 string
token1 string
fee uint32
width uint32
}
14 changes: 14 additions & 0 deletions contracts/utils.gno
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,17 @@ func computeLiquidityRatio(tokenId uint64, balance *u256.Uint) uint64 {

return percentage.Uint64()
}

func subAmounts(amount0, amount1 string) *u256.Uint {
amount0Parsed, err := u256.FromDecimal(amount0)
if err != nil {
panic(err)
}
amount1Parsed, err := u256.FromDecimal(amount1)
if err != nil {
panic(err)
}

amount0Parsed.Sub(amount0Parsed, amount1Parsed)
return amount0Parsed
}
87 changes: 75 additions & 12 deletions contracts/vault.gno
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ import (
)

var (
vaults avl.Tree // tokenId -> *Vault
accessControl acl.Directory
vaults *avl.Tree // tokenId -> *Vault
accessControl *acl.Directory
)

func init() {
vaults = avl.NewTree()
accessControl = acl.New()

accessControl.AddUserPerm(std.PrevRealm().Addr(), "role", "admin")
}

Expand All @@ -28,7 +31,10 @@ func init() {
// @param tokenId uint64 the vault id
// @param _amount0 string the amount of token0 to deposit
// @param _amount1 string the amount of token1 to deposit
func DepositMulti(tokenId uint64, _amount0 string, _amount1 string) {
// @param _amount0Min string the minimum amount of token0 to deposit
// @param _amount1Min string the minimum amount of token1 to deposit
// @param deadline int64 the deadline for the transaction
func DepositMulti(tokenId uint64, _amount0 string, _amount1 string, _amount0Min string, _amount1Min string, deadline int64) {
vault := mustGetVault(tokenId)
assertVaultPaused(vault)

Expand All @@ -43,11 +49,22 @@ func DepositMulti(tokenId uint64, _amount0 string, _amount1 string) {
approveByRegisterCall(vault.token0, poolAddr, _amount0)
approveByRegisterCall(vault.token1, poolAddr, _amount1)

_, liquidity, _, _, _ := position.IncreaseLiquidity(tokenId, _amount0, _amount1, _amount0, _amount1, time.Now().Unix()+1)
_, liquidity, amount0, amount1, _ := position.IncreaseLiquidity(tokenId, _amount0, _amount1, _amount0Min, _amount1Min, deadline)

increaseBalance(vault, caller.String(), liquidity)

std.Emit("Deposit", caller.String(), strconv.FormatUint(tokenId, 10), _amount0, _amount1, liquidity)
// Send back any leftover tokens
amount0Parsed := subAmounts(_amount0, amount0)
amount1Parsed := subAmounts(_amount1, amount1)

if amount0Parsed.Cmp(u256.NewUint(0)) > 0 {
transferByRegisterCall(vault.token0, caller, amount0Parsed.ToString())
}
if amount1Parsed.Cmp(u256.NewUint(0)) > 0 {
transferByRegisterCall(vault.token1, caller, amount1Parsed.ToString())
}

std.Emit("Deposit", caller.String(), strconv.FormatUint(tokenId, 10), amount0Parsed.ToString(), amount1Parsed.ToString(), liquidity)
}

// DepositSingle deposits a single token into a vault
Expand All @@ -64,6 +81,8 @@ func DepositSingle(tokenId uint64, token string, amount string) {
// Withdraw withdraws tokens from a vault
// @param tokenId uint64 the vault id
// @param amount string the amount of liquidity to withdraw
//
// panic if the amount is greater than the caller's balance
func Withdraw(tokenId uint64, amount string) {
vault := mustGetVault(tokenId)
caller := std.PrevRealm().Addr()
Expand All @@ -72,8 +91,11 @@ func Withdraw(tokenId uint64, amount string) {
if err != nil {
panic(err)
}
if balance.Cmp(parsedAmount) < 0 {
panic("insufficient balance")
}

liquidityRatio := computeLiquidityRatio(tokenId, balance)
liquidityRatio := computeLiquidityRatio(tokenId, parsedAmount)
_, liquidity, _, _, amount0, amount1, _ := position.DecreaseLiquidity(tokenId, liquidityRatio, u256.NewUint(0).ToString(), u256.NewUint(0).ToString(), time.Now().Unix()+1, false)

// Transfer tokens to the caller
Expand All @@ -83,8 +105,10 @@ func Withdraw(tokenId uint64, amount string) {
std.Emit("Withdraw", caller.String(), strconv.FormatUint(tokenId, 10), amount0, amount1, liquidity)
}

func Claim(tokenId uint64) {
func Compound(tokenId uint64) {
vault := mustGetVault(tokenId)

// TODO implement
}

/**
Expand All @@ -99,6 +123,9 @@ func Claim(tokenId uint64) {
// @param tickUpper int32 the upper tick of the pool
// @param _amount0 string the amount of token0 to deposit
// @param _amount1 string the amount of token1 to deposit
// @param _amount0Min string the minimum amount of token0 to deposit
// @param _amount1Min string the minimum amount of token1 to deposit
// @param deadline int64 the deadline for the transaction
func NewVault(
token0 string,
token1 string,
Expand All @@ -107,6 +134,9 @@ func NewVault(
tickUpper int32,
_amount0 string, // *u256.Uint
_amount1 string, // *u256.Uint
_amount0Min string, // *u256.Uint
_amount1Min string, // *u256.Uint
deadline int64,
) {
caller := std.PrevRealm().Addr()
accessControl.HasRole(caller, "admin")
Expand All @@ -120,7 +150,7 @@ func NewVault(
approveByRegisterCall(token0, poolAddr, _amount0)
approveByRegisterCall(token1, poolAddr, _amount1)

tokenId, liquidity, _, _ := position.Mint(token0, token1, fee, tickLower, tickUpper, _amount0, _amount1, _amount0, _amount1, time.Now().Unix()+1, std.CurrentRealm().Addr().String())
tokenId, liquidity, amount0, amount1 := position.Mint(token0, token1, fee, tickLower, tickUpper, _amount0, _amount1, _amount0Min, _amount1Min, deadline, std.CurrentRealm().Addr().String())

// Create the vault and set the admin's balance
vault := &Vault{
Expand All @@ -129,11 +159,22 @@ func NewVault(
token0: token0,
token1: token1,
fee: fee,
width: uint32(tickUpper - tickLower),
}
vault.balances.Set(caller.String(), liquidity)

vaults.Set(strconv.FormatUint(tokenId, 10), vault)

// Send back any leftover tokens
amount0Parsed := subAmounts(_amount0, amount0)
amount1Parsed := subAmounts(_amount1, amount1)

if amount0Parsed.Cmp(u256.NewUint(0)) > 0 {
transferByRegisterCall(vault.token0, caller, amount0Parsed.ToString())
}
if amount1Parsed.Cmp(u256.NewUint(0)) > 0 {
transferByRegisterCall(vault.token1, caller, amount1Parsed.ToString())
}

std.Emit("NewVault", token0, token1, strconv.FormatUint(uint64(fee), 10), strconv.FormatUint(tokenId, 10))
}

Expand All @@ -158,13 +199,35 @@ func AddKeeper(keeper std.Address) {
* KEEPER FUNCTIONS
*/

// Rebalance rebalances the position of a vault
// Reposition reposition a vault into a new tick range
// @param tokenId uint64 the vault id
func Rebalance(tokenId uint64) {
// @param tickLower int32 the lower tick of the pool
// @param tickUpper int32 the upper tick of the pool
// @param _amount0Desired string the amount of token0 to deposit
// @param _amount1Desired string the amount of token1 to deposit
// @param _amount0Min string the minimum amount of token0 to deposit
// @param _amount1Min string the minimum amount of token1 to deposit
func Reposition(
tokenId uint64,
tickLower int32,
tickUpper int32,
_amount0Desired string, // uint256
_amount1Desired string, // uint256
_amount0Min string, // *u256.Uint
_amount1Min string, // *u256.Uint
) {
accessControl.HasRole(std.PrevRealm().Addr(), "keeper")

vault := mustGetVault(tokenId)
assertVaultPaused(vault)

// TODO rebalance the vault
// Check width is correct
if uint32(tickUpper-tickLower) != vault.width {
panic("invalid tick range")
}

// TODO automaticly compute amount0 and amount1
position.Reposition(tokenId, tickLower, tickUpper, _amount0Desired, _amount1Desired, _amount0Min, _amount1Min)

std.Emit("Reposition", strconv.FormatUint(tokenId, 10), strconv.FormatInt(int64(tickLower), 10), strconv.FormatInt(int64(tickUpper), 10))
}