curve + aave + beefy

This commit is contained in:
Laurent Le Houerou 2021-11-14 23:08:37 +04:00
parent 916759a907
commit 73bb337e4b
9 changed files with 262 additions and 0 deletions

View File

@ -0,0 +1,21 @@
pragma solidity >=0.6.0;
interface IDataProvider {
function getReserveTokensAddresses(address asset) external view returns (
address aTokenAddress,
address stableDebtTokenAddress,
address variableDebtTokenAddress
);
function getUserReserveData(address asset, address user) external view returns (
uint256 currentATokenBalance,
uint256 currentStableDebt,
uint256 currentVariableDebt,
uint256 principalStableDebt,
uint256 scaledVariableDebt,
uint256 stableBorrowRate,
uint256 liquidityRate,
uint40 stableRateLastUpdated,
bool usageAsCollateralEnabled
);
}

View File

@ -0,0 +1,6 @@
pragma solidity >=0.6.0;
interface IIncentivesController {
function claimRewards(address[] calldata assets, uint256 amount, address to) external returns (uint256);
function getRewardsBalance(address[] calldata assets, address user) external view returns (uint256);
}

View File

@ -0,0 +1,21 @@
pragma solidity >=0.6.0;
interface ILendingPool {
function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external;
function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external;
function repay(address asset, uint256 amount, uint256 rateMode, address onBehalfOf) external returns (uint256);
function withdraw(address asset, uint256 amount, address to) external returns (uint256);
function getUserAccountData(address user) external view returns (
uint256 totalCollateralETH,
uint256 totalDebtETH,
uint256 availableBorrowsETH,
uint256 currentLiquidationThreshold,
uint256 ltv,
uint256 healthFactor
);
}

62
aave/dataprovider.go Normal file
View File

@ -0,0 +1,62 @@
package aave
import (
"git.lehouerou.net/laurent/evm"
"git.lehouerou.net/laurent/evm/aave/contracts"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
"github.com/shopspring/decimal"
)
type DataProvider struct {
client evm.Client
contract *contracts.DataProvider
}
func NewDataProvider(client evm.Client, address common.Address) (*DataProvider, error) {
contract, err := contracts.NewDataProvider(address, client)
if err != nil {
return nil, errors.Wrap(err, "init contract")
}
return &DataProvider{
client: client,
contract: contract,
}, nil
}
type UserReserveData struct {
CurrentATokenBalance decimal.Decimal
CurrentStableDebt decimal.Decimal
CurrentVariableDebt decimal.Decimal
PrincipalStableDebt decimal.Decimal
ScaledVariableDebt decimal.Decimal
StableBorrowRate decimal.Decimal
LiquidityRate decimal.Decimal
StableRateLastUpdated decimal.Decimal
UsageAsCollateralEnabled bool
}
func (d *DataProvider) UserReserveData(asset common.Address, address common.Address) (UserReserveData, error) {
token, err := d.client.TokenService().TokenByAddress(asset)
if err != nil {
return UserReserveData{}, errors.Wrap(err, "get token")
}
rd, err := d.contract.GetUserReserveData(&bind.CallOpts{}, asset, address)
if err != nil {
return UserReserveData{}, errors.Wrap(err, "calling contract")
}
return UserReserveData{
CurrentATokenBalance: token.ValueFromBigInt(rd.CurrentATokenBalance),
CurrentStableDebt: token.ValueFromBigInt(rd.CurrentStableDebt),
CurrentVariableDebt: token.ValueFromBigInt(rd.CurrentVariableDebt),
PrincipalStableDebt: token.ValueFromBigInt(rd.PrincipalStableDebt),
ScaledVariableDebt: token.ValueFromBigInt(rd.ScaledVariableDebt),
StableBorrowRate: token.ValueFromBigInt(rd.StableBorrowRate),
LiquidityRate: token.ValueFromBigInt(rd.LiquidityRate),
StableRateLastUpdated: token.ValueFromBigInt(rd.StableRateLastUpdated),
UsageAsCollateralEnabled: rd.UsageAsCollateralEnabled,
}, nil
}

89
aave/lendingpool.go Normal file
View File

@ -0,0 +1,89 @@
package aave
import (
"context"
"math/big"
"git.lehouerou.net/laurent/evm"
"git.lehouerou.net/laurent/evm/aave/contracts"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
"github.com/shopspring/decimal"
)
type LendingPool struct {
client evm.Client
contract *contracts.LendingPool
}
func NewLendingPool(client evm.Client, address common.Address) (*LendingPool, error) {
contract, err := contracts.NewLendingPool(address, client)
if err != nil {
return nil, errors.Wrap(err, "init contract")
}
return &LendingPool{
client: client,
contract: contract,
}, nil
}
type UserAccountData struct {
TotalCollateralETH decimal.Decimal
TotalDebtETH decimal.Decimal
AvailableBorrowsETH decimal.Decimal
CurrentLiquidationThreshold decimal.Decimal
CurrentLtv decimal.Decimal
MaxLtv decimal.Decimal
HealthFactor decimal.Decimal
}
func (uad UserAccountData) BorrowAmountToLtv(ltv decimal.Decimal) decimal.Decimal {
return uad.TotalCollateralETH.Mul(ltv).Div(decimal.NewFromInt(100)).Sub(uad.TotalDebtETH)
}
func (lp *LendingPool) UserAccountDataForAddress(address common.Address) (UserAccountData, error) {
uad, err := lp.contract.GetUserAccountData(&bind.CallOpts{}, address)
if err != nil {
return UserAccountData{}, errors.Wrap(err, "calling contract")
}
res := UserAccountData{
TotalCollateralETH: decimal.NewFromBigInt(uad.TotalCollateralETH, -8),
TotalDebtETH: decimal.NewFromBigInt(uad.TotalDebtETH, -8),
AvailableBorrowsETH: decimal.NewFromBigInt(uad.AvailableBorrowsETH, -8),
CurrentLiquidationThreshold: decimal.NewFromBigInt(uad.CurrentLiquidationThreshold, -2),
MaxLtv: decimal.NewFromBigInt(uad.Ltv, -2),
HealthFactor: decimal.NewFromBigInt(uad.HealthFactor, -18),
}
res.CurrentLtv = res.TotalDebtETH.Div(res.TotalCollateralETH).Mul(decimal.NewFromInt(100))
return res, nil
}
func (lp *LendingPool) Borrow(ctx context.Context, asset common.Address, amount decimal.Decimal) (evm.Transaction, error) {
token, err := lp.client.TokenService().TokenByAddress(asset)
if err != nil {
return nil, errors.Wrap(err, "getting token")
}
return lp.client.Execute(ctx, func(ctx context.Context, opts *evm.TransactOpts) (*types.Transaction, error) {
return lp.contract.Borrow(opts.TransactOpts, asset, token.ValueToBigInt(amount), big.NewInt(2), 0, lp.client.PublicAddress())
})
}
func (lp *LendingPool) Repay(ctx context.Context, asset common.Address, amount decimal.Decimal) (evm.Transaction, error) {
token, err := lp.client.TokenService().TokenByAddress(asset)
if err != nil {
return nil, errors.Wrap(err, "getting token")
}
balance, err := token.Balance()
if err != nil {
return nil, errors.Wrap(err, "getting token balance")
}
if balance.LessThan(amount) {
return nil, errors.Wrapf(err, "balance of %s insufficient. need %s have %s", token.Symbol(), amount, balance)
}
return lp.client.Execute(ctx, func(ctx context.Context, opts *evm.TransactOpts) (*types.Transaction, error) {
return lp.contract.Repay(opts.TransactOpts, asset, token.ValueToBigInt(amount), big.NewInt(2), lp.client.PublicAddress())
})
}

View File

@ -62,6 +62,7 @@ var tokens = map[string]string{
"xJOE": "0x57319d41f71e81f3c65f2a47ca4e001ebafd4f33", "xJOE": "0x57319d41f71e81f3c65f2a47ca4e001ebafd4f33",
"WETH.e": "0x49d5c2bdffac6ce2bfdb6640f4f80f226bc10bab", "WETH.e": "0x49d5c2bdffac6ce2bfdb6640f4f80f226bc10bab",
"WBTC.e": "0x50b7545627a5162F82A992c33b87aDc75187B218", "WBTC.e": "0x50b7545627a5162F82A992c33b87aDc75187B218",
"USDC.e": "0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664",
} }
func NewTokenMapper() evm.TokenMapper { func NewTokenMapper() evm.TokenMapper {
@ -72,5 +73,6 @@ func NewTokenMapper() evm.TokenMapper {
tm.AddAlias("ETH", "WETH.e") tm.AddAlias("ETH", "WETH.e")
tm.AddAlias("BTC", "WBTC.e") tm.AddAlias("BTC", "WBTC.e")
tm.AddAlias("USDC", "USDC.e")
return tm return tm
} }

View File

@ -3,8 +3,10 @@ package beefy
import ( import (
"git.lehouerou.net/laurent/evm" "git.lehouerou.net/laurent/evm"
"git.lehouerou.net/laurent/evm/beefy/contracts" "git.lehouerou.net/laurent/evm/beefy/contracts"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/shopspring/decimal"
) )
type VaultV6 struct { type VaultV6 struct {
@ -29,3 +31,11 @@ func NewVaultV6(client evm.Client, address common.Address) (*VaultV6, error) {
Token: token, Token: token,
}, nil }, nil
} }
func (v *VaultV6) PricePerFullShare() (decimal.Decimal, error) {
ppfs, err := v.contract.GetPricePerFullShare(&bind.CallOpts{})
if err != nil {
return decimal.Zero, errors.Wrap(err, "calling contract")
}
return v.ValueFromBigInt(ppfs), nil
}

50
curve/Pool.go Normal file
View File

@ -0,0 +1,50 @@
package curve
import (
"git.lehouerou.net/laurent/evm"
"git.lehouerou.net/laurent/evm/curve/contracts"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
"github.com/shopspring/decimal"
)
type Pool struct {
client evm.Client
contract *contracts.Pool
lptoken evm.Token
tokens []evm.Token
}
func NewPool(client evm.Client, address common.Address) (*Pool, error) {
contract, err := contracts.NewPool(address, client)
if err != nil {
return nil, errors.Wrap(err, "init contract")
}
lptokenaddress, err := contract.LpToken(&bind.CallOpts{})
if err != nil {
return nil, errors.Wrap(err, "getting lp token address")
}
lptoken, err := client.TokenService().TokenByAddress(lptokenaddress)
if err != nil {
return nil, errors.Wrap(err, "getting lp token")
}
return &Pool{
client: client,
contract: contract,
lptoken: lptoken,
}, nil
}
func (p *Pool) VirtualPrice() (decimal.Decimal, error) {
price, err := p.contract.GetVirtualPrice(&bind.CallOpts{})
if err != nil {
return decimal.Zero, errors.Wrap(err, "calling contract")
}
return decimal.NewFromBigInt(price, -18), nil
}
//func (p *Pool) CalculateTokenAmount(amounts []decimal.Decimal)

1
curve/contracts/pool.abi Normal file

File diff suppressed because one or more lines are too long