Skip to content

Commit

Permalink
updated match operation for zero value transfer
Browse files Browse the repository at this point in the history
  • Loading branch information
Arpan Pujara committed Jan 25, 2022
1 parent b0fad25 commit 032d555
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 14 deletions.
13 changes: 9 additions & 4 deletions services/construction/payloads.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,21 @@ func (a *APIService) ConstructionPayloads(
ctx context.Context,
request *types.ConstructionPayloadsRequest,
) (*types.ConstructionPayloadsResponse, *types.Error) {
fromOp, toOp, err := matchTransferOperations(request.Operations)
if err != nil {
return nil, svcErrors.WrapErr(svcErrors.ErrUnclearIntent, err)
}

// Convert map to Metadata struct
var metadata metadata
if err := unmarshalJSONMap(request.Metadata, &metadata); err != nil {
return nil, svcErrors.WrapErr(svcErrors.ErrUnableToParseIntermediateResult, err)
}
var isContractCall bool = false
if hasData(metadata.Data) && !hasTransferData(metadata.Data) {
isContractCall = true
}

fromOp, toOp, err := matchTransferOperations(request.Operations, isContractCall)
if err != nil {
return nil, svcErrors.WrapErr(svcErrors.ErrUnclearIntent, err)
}

if err := validateRequest(fromOp, toOp, metadata); err != nil {
return nil, svcErrors.WrapErr(svcErrors.ErrBadRequest, err)
Expand Down
72 changes: 69 additions & 3 deletions services/construction/preprocess.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,14 @@ func (a *APIService) ConstructionPreprocess(
ctx context.Context,
request *types.ConstructionPreprocessRequest,
) (*types.ConstructionPreprocessResponse, *types.Error) {
fromOp, toOp, err := matchTransferOperations(request.Operations)
var isContractCall bool = false
if _, ok := request.Metadata["method_signature"]; ok {
isContractCall = true
}
fromOp, toOp, err := matchTransferOperations(request.Operations, isContractCall)
if err != nil {
return nil, svcErrors.WrapErr(svcErrors.ErrUnclearIntent, err)
}

fromAdd := fromOp.Account.Address
toAdd := toOp.Account.Address

Expand Down Expand Up @@ -169,11 +172,74 @@ func (a *APIService) ConstructionPreprocess(

// matchTransferOperations attempts to match a slice of operations with a `transfer`
// intent. This will match both Native token (Matic) and ERC20 tokens
func matchTransferOperations(operations []*types.Operation) (
func matchTransferOperations(operations []*types.Operation, isContractCall bool) (
*types.Operation,
*types.Operation,
error,
) {
valueOne, err := strconv.ParseInt(operations[0].Amount.Value, 10, 64)
if err != nil {
log.Fatal(err)
}
fmt.Println("in 0 value")
valueTwo, err := strconv.ParseInt(operations[1].Amount.Value, 10, 64)
if err != nil {
log.Fatal(err)
}
if isContractCall && valueOne == 0 {
fmt.Println("value one...!!!", valueOne)
fmt.Println("value two..!!!", valueTwo)
if valueOne != valueTwo {
return nil, nil, errors.New("for generic call both values should be zero")
}
descriptions := &parser.Descriptions{
OperationDescriptions: []*parser.OperationDescription{
{
Type: polygon.CallOpType,
Account: &parser.AccountDescription{
Exists: true,
},
Amount: &parser.AmountDescription{
Exists: true,
Sign: parser.AnyAmountSign,
},
},
{
Type: polygon.CallOpType,
Account: &parser.AccountDescription{
Exists: true,
},
Amount: &parser.AmountDescription{
Exists: true,
Sign: parser.AnyAmountSign,
},
},
},
ErrUnmatched: true,
}

matches, err := parser.MatchOperations(descriptions, operations)
if err != nil {
return nil, nil, err
}

fmt.Println("matches..!!", matches[0])

fromOp, _ := matches[0].First()
toOp, _ := matches[1].First()

// Manually validate currencies since we cannot rely on parser
if fromOp.Amount.Currency == nil || toOp.Amount.Currency == nil {
return nil, nil, errors.New("missing currency")
}

if !reflect.DeepEqual(fromOp.Amount.Currency, toOp.Amount.Currency) {
return nil, nil, errors.New("from and to currencies are not equal")
}

return fromOp, toOp, nil

}
descriptions := &parser.Descriptions{
OperationDescriptions: []*parser.OperationDescription{
{
Expand Down
34 changes: 27 additions & 7 deletions services/construction/preprocess_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ var (
preprocessFromAddress = fromAddress
preprocessToAddress = toAddress
preprocessTokenContractAddress = tokenContractAddress

preprocessTransferValue = uint64(1)
preprocessTransferValueHex = hexutil.EncodeUint64(preprocessTransferValue)
preprocessData = "0xa9059cbb000000000000000000000000efd3dc58d60af3295b92ecd484caeb3a2f30b3e70000000000000000000000000000000000000000000000000000000000000001" // nolint
preprocessGasPrice = uint64(100000000000)
preprocessGasPriceHex = hexutil.EncodeUint64(preprocessGasPrice)
preprocessGenericData = "0x095ea7b3000000000000000000000000d10a72cf054650931365cc44d912a4fd7525705800000000000000000000000000000000000000000000000000000000000003e8"
preprocessZeroTransferValue = uint64(0)
preprocessTransferValue = uint64(1)
preprocessTransferValueHex = hexutil.EncodeUint64(preprocessTransferValue)
preprocessData = "0xa9059cbb000000000000000000000000efd3dc58d60af3295b92ecd484caeb3a2f30b3e70000000000000000000000000000000000000000000000000000000000000001" // nolint
preprocessGasPrice = uint64(100000000000)
preprocessGasPriceHex = hexutil.EncodeUint64(preprocessGasPrice)
preprocessGenericData = "0x095ea7b3000000000000000000000000d10a72cf054650931365cc44d912a4fd7525705800000000000000000000000000000000000000000000000000000000000003e8"
)

func TestPreprocess(t *testing.T) {
Expand Down Expand Up @@ -131,6 +131,26 @@ func TestPreprocess(t *testing.T) {
},
},
},
"happy path: Generic Contract call with zero transfer value": {
operations: templateOperations(preprocessZeroTransferValue, polygon.Currency),
metadata: map[string]interface{}{
"nonce": "34",
"method_signature": "approve(address,uint256)",
"method_args": []string{"0xD10a72Cf054650931365Cc44D912a4FD75257058", "1000"},
},
expectedResponse: &types.ConstructionPreprocessResponse{
Options: map[string]interface{}{
"from": preprocessFromAddress,
"to": preprocessToAddress, // it will be contract address user need to pass in operation
"value": "0x0",
"contract_address": preprocessToAddress,
"data": preprocessGenericData,
"nonce": "0x22",
"method_signature": "approve(address,uint256)",
"method_args": []interface{}{"0xD10a72Cf054650931365Cc44D912a4FD75257058", "1000"},
},
},
},
"happy path: native currency with gas price": {
operations: templateOperations(preprocessTransferValue, polygon.Currency),
metadata: map[string]interface{}{
Expand Down
1 change: 1 addition & 0 deletions services/construction/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/coinbase/rosetta-sdk-go/types"
"github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/polygon-rosetta/polygon"

"golang.org/x/crypto/sha3"
)

Expand Down

0 comments on commit 032d555

Please sign in to comment.