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

Update contract v4_2 #27

Merged
merged 12 commits into from
Jun 17, 2024
389 changes: 389 additions & 0 deletions contracts/feralfile-exhibition-v4_2/feralfile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,389 @@
package feralfilev4_2

import (
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"math/big"
"strconv"
"strings"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"

ethereum "github.com/bitmark-inc/account-vault-ethereum"
feralfilev4 "github.com/bitmark-inc/feralfile-exhibition-smart-contract/go-binding/feralfile-exhibition-v4_2"
)

type FeralfileExhibitionV4_2Contract struct {
contractAddress string
}

func FeralfileExhibitionV4_2ContractFactory(contractAddress string) ethereum.Contract {
return &FeralfileExhibitionV4_2Contract{
contractAddress: contractAddress,
}
}

// Deploy deploys the smart contract to ethereum blockchain
func (c *FeralfileExhibitionV4_2Contract) Deploy(
wallet *ethereum.Wallet,
arguments json.RawMessage) (string, string, error) {
var params struct {
Name string `json:"name"`
Symbol string `json:"symbol"`
Signer common.Address `json:"signer"`
Vault common.Address `json:"vault"`
CostReceiver common.Address `json:"cost_receiver"`
ContractURI string `json:"contract_uri"`
IsBurnable bool `json:"is_burnable"`
IsBridgeable bool `json:"is_bridgeable"`
SeriesIDs []*big.Int `json:"series_ids"`
SeriesMaxSupplies []*big.Int `json:"series_max_supplies"`
SeriesNextTokenIds []*big.Int `json:"series_next_token_ids"`
}

if err := json.Unmarshal(arguments, &params); err != nil {
return "", "", err
}

t, err := wallet.Transactor()
if err != nil {
return "", "", err
}

address, tx, _, err := feralfilev4.DeployFeralfileExhibitionV42(
t,
wallet.RPCClient(),
params.Name,
params.Symbol,
params.IsBurnable,
params.IsBridgeable,
params.Signer,
params.Vault,
params.CostReceiver,
params.ContractURI,
params.SeriesIDs,
params.SeriesMaxSupplies,
params.SeriesNextTokenIds,
)
if err != nil {
return "", "", err
}
return address.String(), tx.Hash().String(), nil
}

// Call is the entry function for account vault to interact with a smart contract.
func (c *FeralfileExhibitionV4_2Contract) Call(
wallet *ethereum.Wallet,
method,
fund string,
arguments json.RawMessage,
noSend bool,
gasLimit uint64,
gasPrice *int64,
nonce *uint64) (*types.Transaction, error) {
contractAddr := common.HexToAddress(c.contractAddress)
contract, err := feralfilev4.NewFeralfileExhibitionV42(contractAddr, wallet.RPCClient())
if err != nil {
return nil, err
}

t, err := wallet.Transactor()
if err != nil {
return nil, err
}

t.NoSend = noSend
t.GasLimit = gasLimit
if gasPrice != nil && *gasPrice != 0 {
t.GasPrice = big.NewInt(*gasPrice * params.Wei)
}

if nonce != nil {
t.Nonce = big.NewInt(int64(*nonce))
}

params, err := c.Parse(method, arguments)
if nil != err {
return nil, err
}

switch method {
case "burnArtworks":
if len(params) != 1 {
return nil, errors.New("Invalid parameters")
}

tokenIDs, ok := params[0].([]*big.Int)
if !ok {
return nil, errors.New("Invalid token burn parameters")
}

return contract.BurnArtworks(t, tokenIDs)
case "mintArtworks":
if len(params) != 1 {
return nil, errors.New("Invalid parameters")
}

mintData, ok := params[0].([]feralfilev4.FeralfileExhibitionV4MintData)
if !ok {
return nil, errors.New("Invalid token mint parameters")
}

return contract.MintArtworks(t, mintData)
case "setTokenBaseURI":
if len(params) != 1 {
return nil, errors.New("Invalid parameters")
}

baseURI, ok := params[0].(string)
if !ok {
return nil, errors.New("Invalid token base URI")
}

return contract.SetTokenBaseURI(t, baseURI)
case "startSale":
return contract.StartSale(t)
case "transferOwnership":
if len(params) != 1 {
return nil, errors.New("Invalid parameters")
}

newOwner, ok := params[0].(common.Address)
if !ok {
return nil, errors.New("Invalid new owner")
}

return contract.TransferOwnership(t, newOwner)
case "buyBulkArtworks":
if len(params) != 4 {
return nil, errors.New("Invalid parameters")
}

r, ok := params[0].([32]byte)
if !ok {
return nil, fmt.Errorf("invalid r")
}

s, ok := params[1].([32]byte)
if !ok {
return nil, fmt.Errorf("invalid s")
}

v, ok := params[2].(uint8)
if !ok {
return nil, fmt.Errorf("invalid v")
}

saleData, ok := params[3].(feralfilev4.IFeralfileSaleDataV2SaleDataV2)
if !ok {
return nil, fmt.Errorf("invalid sale data")
}

return contract.BuyBulkArtworks(t, r, s, v, saleData)
case "setApprovalForAll":
if len(params) != 2 {
return nil, errors.New("Invalid parameters")
}

operator, ok := params[0].(common.Address)
if !ok {
return nil, errors.New("Invalid operator")
}

approved, ok := params[1].(bool)
if !ok {
return nil, errors.New("Invalid approved")
}

t.GasLimit = gasLimit

return contract.SetApprovalForAll(t, operator, approved)
case "setAdvanceSetting":
if len(params) != 2 {
return nil, errors.New("Invalid parameters")
}

return contract.SetAdvanceSetting(t, params[0].([]common.Address), params[1].([]*big.Int))
default:
return nil, fmt.Errorf("unsupported method")
}
}

func (c *FeralfileExhibitionV4_2Contract) Pack(
method string,
arguments json.RawMessage) ([]byte, error) {
abi, err := feralfilev4.FeralfileExhibitionV42MetaData.GetAbi()
if nil != err {
return nil, err
}

parsedArgs, err := c.Parse(method, arguments)
if nil != err {
return nil, err
}

return abi.Pack(method, parsedArgs...)
}

func (c *FeralfileExhibitionV4_2Contract) Parse(
method string,
arguments json.RawMessage) ([]interface{}, error) {
switch method {
case "startSale":
return nil, nil
case "burnArtworks":
var params []ethereum.BigInt
if err := json.Unmarshal(arguments, &params); err != nil {
return nil, err
}
if len(params) == 0 {
return nil, errors.New("Invalid token burn parameters")
}

tokenIDs := make([]*big.Int, len(params))
for i, v := range params {
tokenID := v.Int
tokenIDs[i] = &tokenID
}

return []interface{}{tokenIDs}, nil
case "mintArtworks":
var params []struct {
SeriesID ethereum.BigInt `json:"series_id"`
TokenID ethereum.BigInt `json:"token_id"`
Owner common.Address `json:"owner"`
}
if err := json.Unmarshal(arguments, &params); err != nil {
return nil, err
}
if len(params) == 0 {
return nil, errors.New("Invalid token mint parameters")
}

mintData := make([]feralfilev4.FeralfileExhibitionV4MintData, len(params))
for i := 0; i < len(params); i++ {
mintData[i] = feralfilev4.FeralfileExhibitionV4MintData{
SeriesId: &params[i].SeriesID.Int,
TokenId: &params[i].TokenID.Int,
Owner: params[i].Owner,
}
}

return []interface{}{mintData}, nil
case "setTokenBaseURI":
baseURI := strings.Trim(string(arguments), "\"")
if baseURI == "" {
return nil, errors.New("Invalid token base URI")
}
return []interface{}{baseURI}, nil
case "transferOwnership":
var newOwner common.Address
if err := json.Unmarshal(arguments, &newOwner); err != nil {
return nil, err
}
return []interface{}{newOwner}, nil
case "setApprovalForAll":
var params struct {
Operator common.Address `json:"operator"`
Approved bool `json:"approved"`
}
if err := json.Unmarshal(arguments, &params); err != nil {
return nil, err
}

return []interface{}{params.Operator, params.Approved}, nil
case "buyBulkArtworks":
var params struct {
SaleData struct {
Price ethereum.BigInt `json:"price"`
Cost ethereum.BigInt `json:"cost"`
ExpiryTime ethereum.BigInt `json:"expiryTime"`
Destination common.Address `json:"destination"`
Nonce ethereum.BigInt `json:"nonce"`
SeriesID ethereum.BigInt `json:"seriesId"`
Quantity uint16 `json:"quantity"`
RevenueShares []struct {
Recipient common.Address `json:"recipient"`
Bps ethereum.BigInt `json:"bps"`
} `json:"revenueShares"`
PayByVaultContract bool `json:"payByVaultContract"`
} `json:"saleData"`
R string `json:"r"`
S string `json:"s"`
V string `json:"v"`
}

if err := json.Unmarshal(arguments, &params); err != nil {
return nil, err
}

rVal, err := hex.DecodeString(strings.Replace(params.R, "0x", "", -1))
if err != nil {
return nil, err
}
sVal, err := hex.DecodeString(strings.Replace(params.S, "0x", "", -1))
if err != nil {
return nil, err
}
vVal, err := strconv.ParseUint(strings.Replace(params.V, "0x", "", -1), 16, 64)
if err != nil {
return nil, err
}
if len(rVal) != 32 || len(sVal) != 32 {
return nil, errors.New("required signature length is 32")
}
var r32Val [32]byte
var s32Val [32]byte
copy(r32Val[:], rVal)
copy(s32Val[:], sVal)

revenueShares := make([]feralfilev4.IFeralfileSaleDataRevenueShare, 0)
for _, v := range params.SaleData.RevenueShares {
bps := v.Bps.Int
revenueShares = append(revenueShares, feralfilev4.IFeralfileSaleDataRevenueShare{
Recipient: v.Recipient,
Bps: &bps,
})
}

saleData := feralfilev4.IFeralfileSaleDataV2SaleDataV2{
Price: &params.SaleData.Price.Int,
Cost: &params.SaleData.Cost.Int,
ExpiryTime: &params.SaleData.ExpiryTime.Int,
Destination: params.SaleData.Destination,
Nonce: &params.SaleData.Nonce.Int,
SeriesID: &params.SaleData.SeriesID.Int,
Quantity: params.SaleData.Quantity,
RevenueShares: revenueShares,
PayByVaultContract: params.SaleData.PayByVaultContract,
}

return []interface{}{r32Val, s32Val, uint8(vVal), saleData}, nil
case "setAdvanceSetting":
var params struct {
AdvanceAddresses []common.Address `json:"advance_addresses"`
AdvanceAmounts []ethereum.BigInt `json:"advance_amounts"`
}
if err := json.Unmarshal(arguments, &params); err != nil {
return nil, err
}

advanceAmounts := make([]*big.Int, len(params.AdvanceAmounts))
for i, v := range params.AdvanceAmounts {
amount := v.Int // closure issue
advanceAmounts[i] = &amount
}

return []interface{}{params.AdvanceAddresses, advanceAmounts}, nil
default:
return nil, fmt.Errorf("unsupported method")
}
}

func init() {
ethereum.RegisterContract("FeralfileExhibitionV4_2", FeralfileExhibitionV4_2ContractFactory)
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/bitmark-inc/account-vault-ethereum
go 1.20

require (
github.com/bitmark-inc/feralfile-exhibition-smart-contract/go-binding v0.0.0-20240420161158-7827629e2797
github.com/bitmark-inc/feralfile-exhibition-smart-contract/go-binding v0.0.0-20240617045334-b5d26d3a3dec
github.com/ethereum/go-ethereum v1.13.10
github.com/miguelmota/go-ethereum-hdwallet v0.1.1
github.com/stretchr/testify v1.8.4
Expand Down
Loading
Loading