223 lines
6.3 KiB
Go
223 lines
6.3 KiB
Go
package mutations
|
|
|
|
import (
|
|
"math/big"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"git.lehouerou.net/laurent/sorare/starkware"
|
|
)
|
|
|
|
type Transfer struct {
|
|
Amount string `graphql:"amountAsString:amount"`
|
|
Nonce int `graphql:"nonce"`
|
|
SenderVaultId int `graphql:"senderVaultId"`
|
|
Token string `graphql:"token"`
|
|
ReceiverVaultId int `graphql:"receiverVaultId"`
|
|
ReceiverPublicKey string `graphql:"receiverPublicKey"`
|
|
ExpirationTimestamp int `graphql:"expirationTimestamp"`
|
|
Condition string `graphql:"condition"`
|
|
FeeInfoUser *struct {
|
|
FeeLimit string `graphql:"feeLimit"`
|
|
TokenId string `graphql:"tokenId"`
|
|
SourceVaultId int `graphql:"sourceVaultId"`
|
|
}
|
|
}
|
|
|
|
func (t Transfer) hash() (string, error) {
|
|
token := t.Token
|
|
if strings.HasPrefix(token, "0x") {
|
|
token = token[2:]
|
|
}
|
|
receiverPublicKey := t.ReceiverPublicKey
|
|
if strings.HasPrefix(receiverPublicKey, "0x") {
|
|
receiverPublicKey = receiverPublicKey[2:]
|
|
}
|
|
condition := t.Condition
|
|
if strings.HasPrefix(condition, "0x") {
|
|
condition = condition[2:]
|
|
}
|
|
amountInt, err := strconv.ParseInt(t.Amount, 10, 64)
|
|
if err != nil {
|
|
return "", errors.Wrap(err, "parsing amount")
|
|
}
|
|
amountBn := big.NewInt(amountInt)
|
|
nonceBn := big.NewInt(int64(t.Nonce))
|
|
senderVaultIdBn := big.NewInt(int64(t.SenderVaultId))
|
|
receiverVaultIdBn := big.NewInt(int64(t.ReceiverVaultId))
|
|
expirationTimestampBn := big.NewInt(int64(t.ExpirationTimestamp))
|
|
if t.FeeInfoUser != nil {
|
|
feeVaultIdBn := big.NewInt(int64(t.FeeInfoUser.SourceVaultId))
|
|
feeLimitInt, err := strconv.ParseInt(t.FeeInfoUser.FeeLimit, 10, 64)
|
|
if err != nil {
|
|
return "", errors.Wrap(err, "parsing feeLimit")
|
|
}
|
|
feeLimitBn := big.NewInt(feeLimitInt)
|
|
feeToken := t.FeeInfoUser.TokenId
|
|
if strings.HasPrefix(feeToken, "0x") {
|
|
feeToken = feeToken[2:]
|
|
}
|
|
instructionType := big.NewInt(4)
|
|
if t.Condition != "" {
|
|
instructionType = big.NewInt(5)
|
|
}
|
|
|
|
return hashTransferWithFee(
|
|
instructionType,
|
|
senderVaultIdBn,
|
|
receiverVaultIdBn,
|
|
amountBn,
|
|
nonceBn,
|
|
expirationTimestampBn,
|
|
token,
|
|
receiverPublicKey,
|
|
feeToken,
|
|
feeVaultIdBn,
|
|
feeLimitBn,
|
|
condition,
|
|
)
|
|
} else {
|
|
instructionType := big.NewInt(1)
|
|
if t.Condition != "" {
|
|
instructionType = big.NewInt(2)
|
|
}
|
|
return hashMsg(
|
|
instructionType,
|
|
senderVaultIdBn,
|
|
receiverVaultIdBn,
|
|
amountBn,
|
|
big.NewInt(0),
|
|
nonceBn,
|
|
expirationTimestampBn,
|
|
token,
|
|
receiverPublicKey,
|
|
condition,
|
|
)
|
|
}
|
|
|
|
}
|
|
|
|
func hashMsg(
|
|
instructionType *big.Int,
|
|
senderVaultId *big.Int,
|
|
receiverVaultId *big.Int,
|
|
amount0 *big.Int,
|
|
amount1 *big.Int,
|
|
nonce *big.Int,
|
|
expirationTimestamp *big.Int,
|
|
transferToken string,
|
|
reveiverPublicKey string,
|
|
condition string) (string, error) {
|
|
|
|
packedMessage1 := big.NewInt(0).Set(instructionType)
|
|
packedMessage1.Lsh(packedMessage1, 31)
|
|
packedMessage1.Add(packedMessage1, senderVaultId)
|
|
packedMessage1.Lsh(packedMessage1, 31)
|
|
packedMessage1.Add(packedMessage1, receiverVaultId)
|
|
packedMessage1.Lsh(packedMessage1, 63)
|
|
packedMessage1.Add(packedMessage1, amount0)
|
|
packedMessage1.Lsh(packedMessage1, 63)
|
|
packedMessage1.Add(packedMessage1, amount1)
|
|
packedMessage1.Lsh(packedMessage1, 31)
|
|
packedMessage1.Add(packedMessage1, nonce)
|
|
packedMessage1.Lsh(packedMessage1, 22)
|
|
packedMessage1.Add(packedMessage1, expirationTimestamp)
|
|
|
|
transferTokenBn, ok := big.NewInt(0).SetString(transferToken, 16)
|
|
if !ok {
|
|
return "", errors.Errorf("transferToken is not a hex string: %s", transferToken)
|
|
}
|
|
reveiverPublicKeyBn, ok := big.NewInt(0).SetString(reveiverPublicKey, 16)
|
|
if !ok {
|
|
return "", errors.Errorf("reveiverPublicKey is not a hex string: %s", reveiverPublicKey)
|
|
}
|
|
if condition == "" {
|
|
return starkware.PedersenHash(
|
|
starkware.PedersenHash(transferTokenBn.String(), reveiverPublicKeyBn.String()),
|
|
packedMessage1.String(),
|
|
), nil
|
|
}
|
|
conditionBn, ok := big.NewInt(0).SetString(condition, 16)
|
|
if !ok {
|
|
return "", errors.Errorf("condition is not a hex string: %s", condition)
|
|
}
|
|
return starkware.PedersenHash(
|
|
starkware.PedersenHash(
|
|
starkware.PedersenHash(
|
|
transferTokenBn.String(),
|
|
reveiverPublicKeyBn.String(),
|
|
),
|
|
conditionBn.String(),
|
|
),
|
|
packedMessage1.String(),
|
|
), nil
|
|
}
|
|
|
|
func hashTransferWithFee(
|
|
instructionType *big.Int,
|
|
senderVaultId *big.Int,
|
|
receiverVaultId *big.Int,
|
|
amount *big.Int,
|
|
nonce *big.Int,
|
|
expirationTimestamp *big.Int,
|
|
transferToken string,
|
|
reveiverPublicKey string,
|
|
feeToken string,
|
|
feeVaultId *big.Int,
|
|
feeLimit *big.Int,
|
|
condition string) (string, error) {
|
|
|
|
packedMessage1 := big.NewInt(0).Set(senderVaultId)
|
|
packedMessage1.Lsh(packedMessage1, 64)
|
|
packedMessage1.Add(packedMessage1, receiverVaultId)
|
|
packedMessage1.Lsh(packedMessage1, 64)
|
|
packedMessage1.Add(packedMessage1, feeVaultId)
|
|
packedMessage1.Lsh(packedMessage1, 32)
|
|
packedMessage1.Add(packedMessage1, nonce)
|
|
|
|
packedMessage2 := big.NewInt(0).Set(instructionType)
|
|
packedMessage2.Lsh(packedMessage2, 64)
|
|
packedMessage2.Add(packedMessage2, amount)
|
|
packedMessage2.Lsh(packedMessage2, 64)
|
|
packedMessage2.Add(packedMessage2, feeLimit)
|
|
packedMessage2.Lsh(packedMessage2, 32)
|
|
packedMessage2.Add(packedMessage2, expirationTimestamp)
|
|
packedMessage2.Lsh(packedMessage2, 81)
|
|
packedMessage2.Add(packedMessage2, big.NewInt(0))
|
|
|
|
transferTokenBn, ok := big.NewInt(0).SetString(transferToken, 16)
|
|
if !ok {
|
|
return "", errors.Errorf("transferToken is not a hex string: %s", transferToken)
|
|
}
|
|
reveiverPublicKeyBn, ok := big.NewInt(0).SetString(reveiverPublicKey, 16)
|
|
if !ok {
|
|
return "", errors.Errorf("reveiverPublicKey is not a hex string: %s", reveiverPublicKey)
|
|
}
|
|
feeTokenbn, ok := big.NewInt(0).SetString(feeToken, 16)
|
|
if !ok {
|
|
return "", errors.Errorf("feeToken is not a hex string: %s", feeToken)
|
|
}
|
|
|
|
tmpHash := starkware.PedersenHash(
|
|
starkware.PedersenHash(transferTokenBn.String(), feeTokenbn.String()),
|
|
reveiverPublicKeyBn.String(),
|
|
)
|
|
if condition == "" {
|
|
return starkware.PedersenHash(
|
|
starkware.PedersenHash(tmpHash, packedMessage1.String()),
|
|
packedMessage2.String(),
|
|
), nil
|
|
}
|
|
conditionBn, ok := big.NewInt(0).SetString(condition, 16)
|
|
if !ok {
|
|
return "", errors.Errorf("condition is not a hex string: %s", condition)
|
|
}
|
|
return starkware.PedersenHash(
|
|
starkware.PedersenHash(
|
|
starkware.PedersenHash(tmpHash, conditionBn.String()), packedMessage1.String()),
|
|
packedMessage2.String(),
|
|
), nil
|
|
}
|