Skip to content

Commit c169a23

Browse files
committed
Fix transferFrom function so that we only delete token balances after we've verified the funds are available first - not before
1 parent 7671bdd commit c169a23

File tree

1 file changed

+42
-22
lines changed

1 file changed

+42
-22
lines changed

token-erc-1155/chaincode-go/chaincode/contract.go

+42-22
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package chaincode
99
import (
1010
"encoding/json"
1111
"fmt"
12+
"github.com/hyperledger/fabric-protos-go/ledger/queryresult"
1213
"sort"
1314
"strconv"
1415
"strings"
@@ -949,6 +950,8 @@ func removeBalance(ctx contractapi.TransactionContextInterface, sender string, i
949950
}
950951
defer balanceIterator.Close()
951952

953+
var deferredDeletions = []func() error{}
954+
952955
// Iterate over keys that store balances and add them to partialBalance until
953956
// either the necessary amount is reached or the keys ended
954957
for balanceIterator.HasNext() && partialBalance < neededAmount {
@@ -972,47 +975,64 @@ func removeBalance(ctx contractapi.TransactionContextInterface, sender string, i
972975
selfRecipientKeyNeedsToBeRemoved = true
973976
selfRecipientKey = queryResponse.Key
974977
} else {
975-
err = ctx.GetStub().DelState(queryResponse.Key)
976-
if err != nil {
977-
return fmt.Errorf("failed to delete the state of %v: %v", queryResponse.Key, err)
978-
}
978+
deferredDeletions = append(deferredDeletions, deferredDelete(ctx, queryResponse))
979979
}
980980
}
981981

982982
if partialBalance < neededAmount {
983983
return fmt.Errorf("sender has insufficient funds for token %v, needed funds: %v, available fund: %v", tokenId, neededAmount, partialBalance)
984-
} else if partialBalance > neededAmount {
985-
// Send the remainder back to the sender
986-
remainder, err := sub(partialBalance, neededAmount)
987-
if err != nil {
988-
return err
989-
}
990-
991-
if selfRecipientKeyNeedsToBeRemoved {
992-
// Set balance for the key that has the same address for sender and recipient
993-
err = setBalance(ctx, sender, sender, tokenId, remainder)
984+
} else {
985+
// enough token funds have been found to perform the update
986+
// now we can delete the token entries to supply updated token balances
987+
for _, deleteFn := range deferredDeletions {
988+
err := deleteFn()
994989
if err != nil {
995990
return err
996991
}
997-
} else {
998-
err = addBalance(ctx, sender, sender, tokenId, remainder)
992+
}
993+
if partialBalance > neededAmount {
994+
// Send the remainder back to the sender
995+
remainder, err := sub(partialBalance, neededAmount)
999996
if err != nil {
1000997
return err
1001998
}
1002-
}
1003999

1004-
} else {
1005-
// Delete self recipient key
1006-
err = ctx.GetStub().DelState(selfRecipientKey)
1007-
if err != nil {
1008-
return fmt.Errorf("failed to delete the state of %v: %v", selfRecipientKey, err)
1000+
if selfRecipientKeyNeedsToBeRemoved {
1001+
// Set balance for the key that has the same address for sender and recipient
1002+
err = setBalance(ctx, sender, sender, tokenId, remainder)
1003+
if err != nil {
1004+
return err
1005+
}
1006+
} else {
1007+
err = addBalance(ctx, sender, sender, tokenId, remainder)
1008+
if err != nil {
1009+
return err
1010+
}
1011+
}
1012+
1013+
} else {
1014+
// Delete self recipient key
1015+
err = ctx.GetStub().DelState(selfRecipientKey)
1016+
if err != nil {
1017+
return fmt.Errorf("failed to delete the state of %v: %v", selfRecipientKey, err)
1018+
}
10091019
}
10101020
}
10111021
}
10121022

10131023
return nil
10141024
}
10151025

1026+
func deferredDelete(ctx contractapi.TransactionContextInterface, queryResponse *queryresult.KV) func() error {
1027+
return func() error {
1028+
err := ctx.GetStub().DelState(queryResponse.Key)
1029+
if err != nil {
1030+
return fmt.Errorf("failed to delete the state of %v: %v", queryResponse.Key, err)
1031+
}
1032+
return nil
1033+
}
1034+
}
1035+
10161036
func emitTransferSingle(ctx contractapi.TransactionContextInterface, transferSingleEvent TransferSingle) error {
10171037
transferSingleEventJSON, err := json.Marshal(transferSingleEvent)
10181038
if err != nil {

0 commit comments

Comments
 (0)