Skip to content

Commit

Permalink
intro TxReceiptStatus for statuses defined by EIP658
Browse files Browse the repository at this point in the history
  • Loading branch information
dimroc committed May 3, 2019
1 parent 3b5bd5d commit 36dccd1
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 5 deletions.
6 changes: 3 additions & 3 deletions core/adapters/eth_tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ func TestEthTxAdapter_Perform_FromPendingConfirmations_ConfirmCompletes(t *testi
ethMock := app.MockEthClient()
ethMock.Register("eth_getTransactionReceipt", strpkg.TxReceipt{})
confirmedHash := cltest.NewHash()
receipt := strpkg.TxReceipt{Hash: confirmedHash, BlockNumber: cltest.Int(sentAt)}
receipt := strpkg.TxReceipt{Hash: confirmedHash, BlockNumber: cltest.Int(sentAt), Status: strpkg.TxReceiptSuccess}
ethMock.Register("eth_getTransactionReceipt", receipt)
confirmedAt := sentAt + config.MinOutgoingConfirmations() - 1 // confirmations are 0-based idx
ethMock.Register("eth_blockNumber", utils.Uint64ToHex(confirmedAt))
Expand Down Expand Up @@ -352,7 +352,7 @@ func TestEthTxAdapter_Perform_AppendingTransactionReceipts(t *testing.T) {
sentAt := uint64(23456)

ethMock := app.MockEthClient()
receipt := strpkg.TxReceipt{Hash: cltest.NewHash(), BlockNumber: cltest.Int(sentAt)}
receipt := strpkg.TxReceipt{Hash: cltest.NewHash(), BlockNumber: cltest.Int(sentAt), Status: strpkg.TxReceiptSuccess}
ethMock.Register("eth_getTransactionReceipt", receipt)
confirmedAt := sentAt + config.MinOutgoingConfirmations() - 1 // confirmations are 0-based idx
ethMock.Register("eth_blockNumber", utils.Uint64ToHex(confirmedAt))
Expand All @@ -368,7 +368,7 @@ func TestEthTxAdapter_Perform_AppendingTransactionReceipts(t *testing.T) {

input := sentResult
input.MarkPendingConfirmations()
previousReceipt := strpkg.TxReceipt{Hash: cltest.NewHash(), BlockNumber: cltest.Int(sentAt - 10)}
previousReceipt := strpkg.TxReceipt{Hash: cltest.NewHash(), BlockNumber: cltest.Int(sentAt - 10), Status: strpkg.TxReceiptSuccess}
input.Add("ethereumReceipts", []strpkg.TxReceipt{previousReceipt})

output := adapter.Perform(input, store)
Expand Down
36 changes: 34 additions & 2 deletions core/store/eth_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package store

import (
"context"
"fmt"
"math/big"

ethereum "github.com/ethereum/go-ethereum"
Expand Down Expand Up @@ -157,8 +158,9 @@ func (eth *EthClient) SubscribeToNewHeads(
// TxReceipt holds the block number and the transaction hash of a signed
// transaction that has been written to the blockchain.
type TxReceipt struct {
BlockNumber *models.Big `json:"blockNumber" gorm:"type:numeric"`
Hash common.Hash `json:"transactionHash"`
BlockNumber *models.Big `json:"blockNumber" gorm:"type:numeric"`
Hash common.Hash `json:"transactionHash"`
Status TxReceiptStatus `json:"status"`
}

var emptyHash = common.Hash{}
Expand All @@ -167,3 +169,33 @@ var emptyHash = common.Hash{}
func (txr *TxReceipt) Unconfirmed() bool {
return txr.Hash == emptyHash || txr.BlockNumber == nil
}

// TxReceiptStatus encapsulates the different return values available
// for an ethereum transaction receipt as defined by
// http://eips.ethereum.org/EIPS/eip-658
type TxReceiptStatus string

const (
// TxReceiptRevert represents the status that results in any failure and
// resulting revert.
TxReceiptRevert TxReceiptStatus = "0x0"
// TxReceiptSuccess represents a successful transaction, not resulting in a
// revert.
TxReceiptSuccess = "0x1"
)

// UnmarshalText parses text input to a predefined transaction receipt
// status as defined by Ethereum or an EIP. Returns an error if we encounter
// unexpected input.
func (trs *TxReceiptStatus) UnmarshalText(input []byte) error {
switch TxReceiptStatus(input) {
case TxReceiptRevert:
*trs = TxReceiptRevert
case TxReceiptSuccess:
*trs = TxReceiptSuccess
default:
return fmt.Errorf("unable to convert %s to %T", string(input), trs)
}

return nil
}
66 changes: 66 additions & 0 deletions core/store/eth_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/ethereum/go-ethereum/common"
"github.com/smartcontractkit/chainlink/core/internal/cltest"
"github.com/smartcontractkit/chainlink/core/store"
strpkg "github.com/smartcontractkit/chainlink/core/store"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -124,3 +125,68 @@ func TestEthClient_GetERC20Balance(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, expected, result)
}

func TestTxReceiptStatus_UnmarshalText_Success(t *testing.T) {
t.Parallel()

tests := []struct {
input string
expected store.TxReceiptStatus
}{
{"0x0", store.TxReceiptRevert},
{"0x1", store.TxReceiptSuccess},
}

for _, test := range tests {
t.Run(test.input, func(t *testing.T) {
var ptrs store.TxReceiptStatus
err := ptrs.UnmarshalText([]byte(test.input))
assert.NoError(t, err)
assert.Equal(t, test.expected, ptrs)
})
}
}

func TestTxReceiptStatus_UnmarshalText_Error(t *testing.T) {
t.Parallel()

tests := []struct {
input string
}{
{""},
{"0x"},
}

for _, test := range tests {
t.Run(test.input, func(t *testing.T) {
var ptrs store.TxReceiptStatus
err := ptrs.UnmarshalText([]byte(test.input))
assert.Error(t, err)
})
}
}

func TestTxReceiptStatus_UnmarshalJSON_Success(t *testing.T) {
t.Parallel()

type subject struct {
Status store.TxReceiptStatus `json:"status"`
}

tests := []struct {
input string
expected store.TxReceiptStatus
}{
{`{"status": "0x0"}`, store.TxReceiptRevert},
{`{"status": "0x1"}`, store.TxReceiptSuccess},
}

for _, test := range tests {
t.Run(test.input, func(t *testing.T) {
var dst subject
err := json.Unmarshal([]byte(test.input), &dst)
require.NoError(t, err)
assert.Equal(t, test.expected, dst.Status)
})
}
}

0 comments on commit 36dccd1

Please sign in to comment.