Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mybee
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
vicotor
mybee
Commits
bacba66c
Unverified
Commit
bacba66c
authored
Mar 03, 2021
by
Ralph Pichler
Committed by
GitHub
Mar 03, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chequebook: better event parsing (#1360)
parent
b2145c85
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
320 additions
and
210 deletions
+320
-210
chain.go
pkg/node/chain.go
+3
-7
node.go
pkg/node/node.go
+1
-4
bindings.go
pkg/settlement/swap/chequebook/bindings.go
+0
-4
cashout.go
pkg/settlement/swap/chequebook/cashout.go
+33
-39
cashout_test.go
pkg/settlement/swap/chequebook/cashout_test.go
+27
-70
chequebook.go
pkg/settlement/swap/chequebook/chequebook.go
+7
-17
common_test.go
pkg/settlement/swap/chequebook/common_test.go
+6
-23
factory.go
pkg/settlement/swap/chequebook/factory.go
+13
-34
factory_test.go
pkg/settlement/swap/chequebook/factory_test.go
+12
-12
backend.go
pkg/settlement/swap/transaction/backend.go
+12
-0
event.go
pkg/settlement/swap/transaction/event.go
+58
-0
event_test.go
pkg/settlement/swap/transaction/event_test.go
+148
-0
No files found.
pkg/node/chain.go
View file @
bacba66c
...
...
@@ -157,7 +157,7 @@ func initChequeStoreCashout(
chainID
int64
,
overlayEthAddress
common
.
Address
,
transactionService
transaction
.
Service
,
)
(
chequebook
.
ChequeStore
,
chequebook
.
CashoutService
,
error
)
{
)
(
chequebook
.
ChequeStore
,
chequebook
.
CashoutService
)
{
chequeStore
:=
chequebook
.
NewChequeStore
(
stateStore
,
swapBackend
,
...
...
@@ -168,18 +168,14 @@ func initChequeStoreCashout(
chequebook
.
RecoverCheque
,
)
cashout
,
err
:=
chequebook
.
NewCashoutService
(
cashout
:=
chequebook
.
NewCashoutService
(
stateStore
,
chequebook
.
NewSimpleSwapBindings
,
swapBackend
,
transactionService
,
chequeStore
,
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
return
chequeStore
,
cashout
,
nil
return
chequeStore
,
cashout
}
// InitSwap will initialize and register the swap service.
...
...
pkg/node/node.go
View file @
bacba66c
...
...
@@ -222,7 +222,7 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
return
nil
,
err
}
chequeStore
,
cashoutService
,
err
=
initChequeStoreCashout
(
chequeStore
,
cashoutService
=
initChequeStoreCashout
(
stateStore
,
swapBackend
,
chequebookFactory
,
...
...
@@ -230,9 +230,6 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
overlayEthAddress
,
transactionService
,
)
if
err
!=
nil
{
return
nil
,
err
}
}
p2ps
,
err
:=
libp2p
.
New
(
p2pCtx
,
signer
,
networkID
,
swarmAddress
,
addr
,
addressbook
,
stateStore
,
logger
,
tracer
,
libp2p
.
Options
{
...
...
pkg/settlement/swap/chequebook/bindings.go
View file @
bacba66c
...
...
@@ -9,7 +9,6 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethersphere/sw3-bindings/v3/simpleswapfactory"
)
...
...
@@ -19,8 +18,6 @@ type SimpleSwapBinding interface {
Issuer
(
*
bind
.
CallOpts
)
(
common
.
Address
,
error
)
TotalPaidOut
(
*
bind
.
CallOpts
)
(
*
big
.
Int
,
error
)
PaidOut
(
*
bind
.
CallOpts
,
common
.
Address
)
(
*
big
.
Int
,
error
)
ParseChequeCashed
(
types
.
Log
)
(
*
simpleswapfactory
.
ERC20SimpleSwapChequeCashed
,
error
)
ParseChequeBounced
(
types
.
Log
)
(
*
simpleswapfactory
.
ERC20SimpleSwapChequeBounced
,
error
)
}
type
SimpleSwapBindingFunc
=
func
(
common
.
Address
,
bind
.
ContractBackend
)
(
SimpleSwapBinding
,
error
)
...
...
@@ -44,7 +41,6 @@ func NewERC20Bindings(address common.Address, backend bind.ContractBackend) (ERC
// SimpleSwapFactoryBinding is the interface for the generated go bindings for SimpleSwapFactory
type
SimpleSwapFactoryBinding
interface
{
ParseSimpleSwapDeployed
(
types
.
Log
)
(
*
simpleswapfactory
.
SimpleSwapFactorySimpleSwapDeployed
,
error
)
DeployedContracts
(
*
bind
.
CallOpts
,
common
.
Address
)
(
bool
,
error
)
ERC20Address
(
*
bind
.
CallOpts
)
(
common
.
Address
,
error
)
}
...
...
pkg/settlement/swap/chequebook/cashout.go
View file @
bacba66c
...
...
@@ -9,14 +9,11 @@ import (
"errors"
"fmt"
"math/big"
"strings"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethersphere/bee/pkg/settlement/swap/transaction"
"github.com/ethersphere/bee/pkg/storage"
"github.com/ethersphere/sw3-bindings/v3/simpleswapfactory"
)
var
(
...
...
@@ -33,12 +30,10 @@ type CashoutService interface {
}
type
cashoutService
struct
{
store
storage
.
StateStorer
simpleSwapBindingFunc
SimpleSwapBindingFunc
backend
transaction
.
Backend
transactionService
transaction
.
Service
chequebookABI
abi
.
ABI
chequeStore
ChequeStore
store
storage
.
StateStorer
backend
transaction
.
Backend
transactionService
transaction
.
Service
chequeStore
ChequeStore
}
// CashoutStatus is the action plus its result
...
...
@@ -65,28 +60,28 @@ type cashoutAction struct {
TxHash
common
.
Hash
Cheque
SignedCheque
// the cheque that was used to cashout which may be different from the latest cheque
}
type
chequeCashedEvent
struct
{
Beneficiary
common
.
Address
Recipient
common
.
Address
Caller
common
.
Address
TotalPayout
*
big
.
Int
CumulativePayout
*
big
.
Int
CallerPayout
*
big
.
Int
}
// NewCashoutService creates a new CashoutService
func
NewCashoutService
(
store
storage
.
StateStorer
,
simpleSwapBindingFunc
SimpleSwapBindingFunc
,
backend
transaction
.
Backend
,
transactionService
transaction
.
Service
,
chequeStore
ChequeStore
,
)
(
CashoutService
,
error
)
{
chequebookABI
,
err
:=
abi
.
JSON
(
strings
.
NewReader
(
simpleswapfactory
.
ERC20SimpleSwapABI
))
if
err
!=
nil
{
return
nil
,
err
}
)
CashoutService
{
return
&
cashoutService
{
store
:
store
,
simpleSwapBindingFunc
:
simpleSwapBindingFunc
,
backend
:
backend
,
transactionService
:
transactionService
,
chequebookABI
:
chequebookABI
,
chequeStore
:
chequeStore
,
},
nil
store
:
store
,
backend
:
backend
,
transactionService
:
transactionService
,
chequeStore
:
chequeStore
,
}
}
// cashoutActionKey computes the store key for the last cashout action for the chequebook
...
...
@@ -101,7 +96,7 @@ func (s *cashoutService) CashCheque(ctx context.Context, chequebook, recipient c
return
common
.
Hash
{},
err
}
callData
,
err
:=
s
.
chequebookABI
.
Pack
(
"cashChequeBeneficiary"
,
recipient
,
cheque
.
CumulativePayout
,
cheque
.
Signature
)
callData
,
err
:=
chequebookABI
.
Pack
(
"cashChequeBeneficiary"
,
recipient
,
cheque
.
CumulativePayout
,
cheque
.
Signature
)
if
err
!=
nil
{
return
common
.
Hash
{},
err
}
...
...
@@ -188,25 +183,24 @@ func (s *cashoutService) parseCashChequeBeneficiaryReceipt(chequebookAddress com
Bounced
:
false
,
}
binding
,
err
:=
s
.
simpleSwapBindingFunc
(
chequebookAddress
,
s
.
backend
)
var
cashedEvent
chequeCashedEvent
err
:=
transaction
.
FindSingleEvent
(
&
chequebookABI
,
receipt
,
chequebookAddress
,
chequeCashedEventType
,
&
cashedEvent
)
if
err
!=
nil
{
return
nil
,
err
}
for
_
,
log
:=
range
receipt
.
Logs
{
if
log
.
Address
!=
chequebookAddress
{
continue
}
if
event
,
err
:=
binding
.
ParseChequeCashed
(
*
log
);
err
==
nil
{
result
.
Beneficiary
=
event
.
Beneficiary
result
.
Caller
=
event
.
Caller
result
.
CallerPayout
=
event
.
CallerPayout
result
.
TotalPayout
=
event
.
TotalPayout
result
.
CumulativePayout
=
event
.
CumulativePayout
result
.
Recipient
=
event
.
Recipient
}
else
if
_
,
err
:=
binding
.
ParseChequeBounced
(
*
log
);
err
==
nil
{
result
.
Bounced
=
true
}
result
.
Beneficiary
=
cashedEvent
.
Beneficiary
result
.
Caller
=
cashedEvent
.
Caller
result
.
CallerPayout
=
cashedEvent
.
CallerPayout
result
.
TotalPayout
=
cashedEvent
.
TotalPayout
result
.
CumulativePayout
=
cashedEvent
.
CumulativePayout
result
.
Recipient
=
cashedEvent
.
Recipient
err
=
transaction
.
FindSingleEvent
(
&
chequebookABI
,
receipt
,
chequebookAddress
,
chequeBouncedEventType
,
nil
)
if
err
==
nil
{
result
.
Bounced
=
true
}
else
if
!
errors
.
Is
(
err
,
transaction
.
ErrEventNotFound
)
{
return
nil
,
err
}
return
result
,
nil
...
...
pkg/settlement/swap/chequebook/cashout_test.go
View file @
bacba66c
...
...
@@ -6,11 +6,9 @@ package chequebook_test
import
(
"context"
"errors"
"math/big"
"testing"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethersphere/bee/pkg/settlement/swap/chequebook"
...
...
@@ -22,11 +20,16 @@ import (
"github.com/ethersphere/sw3-bindings/v3/simpleswapfactory"
)
var
(
chequebookABI
=
transaction
.
ParseABIUnchecked
(
simpleswapfactory
.
ERC20SimpleSwapABI
)
chequeCashedEventType
=
chequebookABI
.
Events
[
"ChequeCashed"
]
chequeBouncedEventType
=
chequebookABI
.
Events
[
"ChequeBounced"
]
)
func
TestCashout
(
t
*
testing
.
T
)
{
chequebookAddress
:=
common
.
HexToAddress
(
"abcd"
)
recipientAddress
:=
common
.
HexToAddress
(
"efff"
)
txHash
:=
common
.
HexToHash
(
"dddd"
)
log1Topic
:=
common
.
HexToHash
(
"eeee"
)
totalPayout
:=
big
.
NewInt
(
100
)
cumulativePayout
:=
big
.
NewInt
(
500
)
...
...
@@ -40,25 +43,8 @@ func TestCashout(t *testing.T) {
}
store
:=
storemock
.
NewStateStore
()
cashoutService
,
err
:=
chequebook
.
NewCashoutService
(
cashoutService
:=
chequebook
.
NewCashoutService
(
store
,
func
(
common
.
Address
,
bind
.
ContractBackend
)
(
chequebook
.
SimpleSwapBinding
,
error
)
{
return
&
simpleSwapBindingMock
{
parseChequeCashed
:
func
(
l
types
.
Log
)
(
*
simpleswapfactory
.
ERC20SimpleSwapChequeCashed
,
error
)
{
if
l
.
Topics
[
0
]
!=
log1Topic
{
t
.
Fatalf
(
"parsing wrong log. wanted %v, got %v"
,
log1Topic
,
l
.
Topics
[
0
])
}
return
&
simpleswapfactory
.
ERC20SimpleSwapChequeCashed
{
Beneficiary
:
cheque
.
Beneficiary
,
Recipient
:
recipientAddress
,
Caller
:
cheque
.
Beneficiary
,
TotalPayout
:
totalPayout
,
CumulativePayout
:
cumulativePayout
,
CallerPayout
:
big
.
NewInt
(
0
),
},
nil
},
},
nil
},
backendmock
.
New
(
backendmock
.
WithTransactionByHashFunc
(
func
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
tx
*
types
.
Transaction
,
isPending
bool
,
err
error
)
{
if
hash
!=
txHash
{
...
...
@@ -70,12 +56,19 @@ func TestCashout(t *testing.T) {
if
hash
!=
txHash
{
t
.
Fatalf
(
"fetching receipt for transaction. wanted %v, got %v"
,
txHash
,
hash
)
}
logData
,
err
:=
chequeCashedEventType
.
Inputs
.
NonIndexed
()
.
Pack
(
totalPayout
,
cumulativePayout
,
big
.
NewInt
(
0
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
return
&
types
.
Receipt
{
Status
:
types
.
ReceiptStatusSuccessful
,
Logs
:
[]
*
types
.
Log
{
{
Address
:
chequebookAddress
,
Topics
:
[]
common
.
Hash
{
log1Topic
},
Topics
:
[]
common
.
Hash
{
chequeCashedEventType
.
ID
,
cheque
.
Beneficiary
.
Hash
(),
recipientAddress
.
Hash
(),
cheque
.
Beneficiary
.
Hash
()},
Data
:
logData
,
},
},
},
nil
...
...
@@ -101,9 +94,6 @@ func TestCashout(t *testing.T) {
}),
),
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
returnedTxHash
,
err
:=
cashoutService
.
CashCheque
(
context
.
Background
(),
chequebookAddress
,
recipientAddress
)
if
err
!=
nil
{
...
...
@@ -154,8 +144,6 @@ func TestCashoutBounced(t *testing.T) {
chequebookAddress
:=
common
.
HexToAddress
(
"abcd"
)
recipientAddress
:=
common
.
HexToAddress
(
"efff"
)
txHash
:=
common
.
HexToHash
(
"dddd"
)
log1Topic
:=
common
.
HexToHash
(
"eeee"
)
logBouncedTopic
:=
common
.
HexToHash
(
"bbbb"
)
totalPayout
:=
big
.
NewInt
(
100
)
cumulativePayout
:=
big
.
NewInt
(
500
)
...
...
@@ -169,31 +157,8 @@ func TestCashoutBounced(t *testing.T) {
}
store
:=
storemock
.
NewStateStore
()
cashoutService
,
err
:=
chequebook
.
NewCashoutService
(
cashoutService
:=
chequebook
.
NewCashoutService
(
store
,
func
(
common
.
Address
,
bind
.
ContractBackend
)
(
chequebook
.
SimpleSwapBinding
,
error
)
{
return
&
simpleSwapBindingMock
{
parseChequeCashed
:
func
(
l
types
.
Log
)
(
*
simpleswapfactory
.
ERC20SimpleSwapChequeCashed
,
error
)
{
if
l
.
Topics
[
0
]
!=
log1Topic
{
return
nil
,
errors
.
New
(
""
)
}
return
&
simpleswapfactory
.
ERC20SimpleSwapChequeCashed
{
Beneficiary
:
cheque
.
Beneficiary
,
Recipient
:
recipientAddress
,
Caller
:
cheque
.
Beneficiary
,
TotalPayout
:
totalPayout
,
CumulativePayout
:
cumulativePayout
,
CallerPayout
:
big
.
NewInt
(
0
),
},
nil
},
parseChequeBounced
:
func
(
l
types
.
Log
)
(
*
simpleswapfactory
.
ERC20SimpleSwapChequeBounced
,
error
)
{
if
l
.
Topics
[
0
]
!=
logBouncedTopic
{
t
.
Fatalf
(
"parsing wrong bounced log. wanted %v, got %v"
,
logBouncedTopic
,
l
.
Topics
[
0
])
}
return
&
simpleswapfactory
.
ERC20SimpleSwapChequeBounced
{},
nil
},
},
nil
},
backendmock
.
New
(
backendmock
.
WithTransactionByHashFunc
(
func
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
*
types
.
Transaction
,
bool
,
error
)
{
if
hash
!=
txHash
{
...
...
@@ -205,16 +170,23 @@ func TestCashoutBounced(t *testing.T) {
if
hash
!=
txHash
{
t
.
Fatalf
(
"fetching receipt for transaction. wanted %v, got %v"
,
txHash
,
hash
)
}
chequeCashedLogData
,
err
:=
chequeCashedEventType
.
Inputs
.
NonIndexed
()
.
Pack
(
totalPayout
,
cumulativePayout
,
big
.
NewInt
(
0
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
return
&
types
.
Receipt
{
Status
:
types
.
ReceiptStatusSuccessful
,
Logs
:
[]
*
types
.
Log
{
{
Address
:
chequebookAddress
,
Topics
:
[]
common
.
Hash
{
log1Topic
},
Topics
:
[]
common
.
Hash
{
chequeCashedEventType
.
ID
,
cheque
.
Beneficiary
.
Hash
(),
recipientAddress
.
Hash
(),
cheque
.
Beneficiary
.
Hash
()},
Data
:
chequeCashedLogData
,
},
{
Address
:
chequebookAddress
,
Topics
:
[]
common
.
Hash
{
logBouncedTopic
},
Topics
:
[]
common
.
Hash
{
chequeBouncedEventType
.
ID
},
},
},
},
nil
...
...
@@ -240,9 +212,6 @@ func TestCashoutBounced(t *testing.T) {
}),
),
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
returnedTxHash
,
err
:=
cashoutService
.
CashCheque
(
context
.
Background
(),
chequebookAddress
,
recipientAddress
)
if
err
!=
nil
{
...
...
@@ -305,11 +274,8 @@ func TestCashoutStatusReverted(t *testing.T) {
}
store
:=
storemock
.
NewStateStore
()
cashoutService
,
err
:=
chequebook
.
NewCashoutService
(
cashoutService
:=
chequebook
.
NewCashoutService
(
store
,
func
(
common
.
Address
,
bind
.
ContractBackend
)
(
chequebook
.
SimpleSwapBinding
,
error
)
{
return
&
simpleSwapBindingMock
{},
nil
},
backendmock
.
New
(
backendmock
.
WithTransactionByHashFunc
(
func
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
tx
*
types
.
Transaction
,
isPending
bool
,
err
error
)
{
if
hash
!=
txHash
{
...
...
@@ -340,9 +306,6 @@ func TestCashoutStatusReverted(t *testing.T) {
}),
),
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
returnedTxHash
,
err
:=
cashoutService
.
CashCheque
(
context
.
Background
(),
chequebookAddress
,
recipientAddress
)
if
err
!=
nil
{
...
...
@@ -387,11 +350,8 @@ func TestCashoutStatusPending(t *testing.T) {
}
store
:=
storemock
.
NewStateStore
()
cashoutService
,
err
:=
chequebook
.
NewCashoutService
(
cashoutService
:=
chequebook
.
NewCashoutService
(
store
,
func
(
common
.
Address
,
bind
.
ContractBackend
)
(
chequebook
.
SimpleSwapBinding
,
error
)
{
return
&
simpleSwapBindingMock
{},
nil
},
backendmock
.
New
(
backendmock
.
WithTransactionByHashFunc
(
func
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
tx
*
types
.
Transaction
,
isPending
bool
,
err
error
)
{
if
hash
!=
txHash
{
...
...
@@ -414,9 +374,6 @@ func TestCashoutStatusPending(t *testing.T) {
}),
),
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
returnedTxHash
,
err
:=
cashoutService
.
CashCheque
(
context
.
Background
(),
chequebookAddress
,
recipientAddress
)
if
err
!=
nil
{
...
...
pkg/settlement/swap/chequebook/chequebook.go
View file @
bacba66c
...
...
@@ -12,7 +12,6 @@ import (
"strings"
"sync"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/pkg/settlement/swap/transaction"
...
...
@@ -33,6 +32,11 @@ var (
ErrOutOfFunds
=
errors
.
New
(
"chequebook out of funds"
)
// ErrInsufficientFunds is the error when the chequebook has not enough free funds for a user action
ErrInsufficientFunds
=
errors
.
New
(
"insufficient token balance"
)
chequebookABI
=
transaction
.
ParseABIUnchecked
(
simpleswapfactory
.
ERC20SimpleSwapABI
)
chequeCashedEventType
=
chequebookABI
.
Events
[
"ChequeCashed"
]
chequeBouncedEventType
=
chequebookABI
.
Events
[
"ChequeBounced"
]
erc20ABI
=
transaction
.
ParseABIUnchecked
(
simpleswapfactory
.
ERC20ABI
)
)
// Service is the main interface for interacting with the nodes chequebook.
...
...
@@ -63,12 +67,10 @@ type service struct {
transactionService
transaction
.
Service
address
common
.
Address
chequebookABI
abi
.
ABI
chequebookInstance
SimpleSwapBinding
ownerAddress
common
.
Address
erc20Address
common
.
Address
erc20ABI
abi
.
ABI
erc20Instance
ERC20Binding
store
storage
.
StateStorer
...
...
@@ -78,16 +80,6 @@ type service struct {
// New creates a new chequebook service for the provided chequebook contract.
func
New
(
backend
transaction
.
Backend
,
transactionService
transaction
.
Service
,
address
,
erc20Address
,
ownerAddress
common
.
Address
,
store
storage
.
StateStorer
,
chequeSigner
ChequeSigner
,
simpleSwapBindingFunc
SimpleSwapBindingFunc
,
erc20BindingFunc
ERC20BindingFunc
)
(
Service
,
error
)
{
chequebookABI
,
err
:=
abi
.
JSON
(
strings
.
NewReader
(
simpleswapfactory
.
ERC20SimpleSwapABI
))
if
err
!=
nil
{
return
nil
,
err
}
erc20ABI
,
err
:=
abi
.
JSON
(
strings
.
NewReader
(
simpleswapfactory
.
ERC20ABI
))
if
err
!=
nil
{
return
nil
,
err
}
chequebookInstance
,
err
:=
simpleSwapBindingFunc
(
address
,
backend
)
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -102,11 +94,9 @@ func New(backend transaction.Backend, transactionService transaction.Service, ad
backend
:
backend
,
transactionService
:
transactionService
,
address
:
address
,
chequebookABI
:
chequebookABI
,
chequebookInstance
:
chequebookInstance
,
ownerAddress
:
ownerAddress
,
erc20Address
:
erc20Address
,
erc20ABI
:
erc20ABI
,
erc20Instance
:
erc20Instance
,
store
:
store
,
chequeSigner
:
chequeSigner
,
...
...
@@ -133,7 +123,7 @@ func (s *service) Deposit(ctx context.Context, amount *big.Int) (hash common.Has
return
common
.
Hash
{},
ErrInsufficientFunds
}
callData
,
err
:=
s
.
erc20ABI
.
Pack
(
"transfer"
,
s
.
address
,
amount
)
callData
,
err
:=
erc20ABI
.
Pack
(
"transfer"
,
s
.
address
,
amount
)
if
err
!=
nil
{
return
common
.
Hash
{},
err
}
...
...
@@ -365,7 +355,7 @@ func (s *service) Withdraw(ctx context.Context, amount *big.Int) (hash common.Ha
return
common
.
Hash
{},
ErrInsufficientFunds
}
callData
,
err
:=
s
.
chequebookABI
.
Pack
(
"withdraw"
,
amount
)
callData
,
err
:=
chequebookABI
.
Pack
(
"withdraw"
,
amount
)
if
err
!=
nil
{
return
common
.
Hash
{},
err
}
...
...
pkg/settlement/swap/chequebook/common_test.go
View file @
bacba66c
...
...
@@ -10,19 +10,12 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethersphere/bee/pkg/settlement/swap/chequebook"
"github.com/ethersphere/sw3-bindings/v3/simpleswapfactory"
)
type
simpleSwapFactoryBindingMock
struct
{
erc20Address
func
(
*
bind
.
CallOpts
)
(
common
.
Address
,
error
)
deployedContracts
func
(
*
bind
.
CallOpts
,
common
.
Address
)
(
bool
,
error
)
parseSimpleSwapDeployed
func
(
types
.
Log
)
(
*
simpleswapfactory
.
SimpleSwapFactorySimpleSwapDeployed
,
error
)
}
func
(
m
*
simpleSwapFactoryBindingMock
)
ParseSimpleSwapDeployed
(
l
types
.
Log
)
(
*
simpleswapfactory
.
SimpleSwapFactorySimpleSwapDeployed
,
error
)
{
return
m
.
parseSimpleSwapDeployed
(
l
)
erc20Address
func
(
*
bind
.
CallOpts
)
(
common
.
Address
,
error
)
deployedContracts
func
(
*
bind
.
CallOpts
,
common
.
Address
)
(
bool
,
error
)
}
func
(
m
*
simpleSwapFactoryBindingMock
)
DeployedContracts
(
o
*
bind
.
CallOpts
,
a
common
.
Address
)
(
bool
,
error
)
{
...
...
@@ -33,12 +26,10 @@ func (m *simpleSwapFactoryBindingMock) ERC20Address(o *bind.CallOpts) (common.Ad
}
type
simpleSwapBindingMock
struct
{
balance
func
(
*
bind
.
CallOpts
)
(
*
big
.
Int
,
error
)
issuer
func
(
*
bind
.
CallOpts
)
(
common
.
Address
,
error
)
totalPaidOut
func
(
o
*
bind
.
CallOpts
)
(
*
big
.
Int
,
error
)
paidOut
func
(
*
bind
.
CallOpts
,
common
.
Address
)
(
*
big
.
Int
,
error
)
parseChequeCashed
func
(
types
.
Log
)
(
*
simpleswapfactory
.
ERC20SimpleSwapChequeCashed
,
error
)
parseChequeBounced
func
(
types
.
Log
)
(
*
simpleswapfactory
.
ERC20SimpleSwapChequeBounced
,
error
)
balance
func
(
*
bind
.
CallOpts
)
(
*
big
.
Int
,
error
)
issuer
func
(
*
bind
.
CallOpts
)
(
common
.
Address
,
error
)
totalPaidOut
func
(
o
*
bind
.
CallOpts
)
(
*
big
.
Int
,
error
)
paidOut
func
(
*
bind
.
CallOpts
,
common
.
Address
)
(
*
big
.
Int
,
error
)
}
func
(
m
*
simpleSwapBindingMock
)
Balance
(
o
*
bind
.
CallOpts
)
(
*
big
.
Int
,
error
)
{
...
...
@@ -53,14 +44,6 @@ func (m *simpleSwapBindingMock) TotalPaidOut(o *bind.CallOpts) (*big.Int, error)
return
m
.
totalPaidOut
(
o
)
}
func
(
m
*
simpleSwapBindingMock
)
ParseChequeCashed
(
l
types
.
Log
)
(
*
simpleswapfactory
.
ERC20SimpleSwapChequeCashed
,
error
)
{
return
m
.
parseChequeCashed
(
l
)
}
func
(
m
*
simpleSwapBindingMock
)
ParseChequeBounced
(
l
types
.
Log
)
(
*
simpleswapfactory
.
ERC20SimpleSwapChequeBounced
,
error
)
{
return
m
.
parseChequeBounced
(
l
)
}
func
(
m
*
simpleSwapBindingMock
)
PaidOut
(
o
*
bind
.
CallOpts
,
c
common
.
Address
)
(
*
big
.
Int
,
error
)
{
return
m
.
paidOut
(
o
,
c
)
}
...
...
pkg/settlement/swap/chequebook/factory.go
View file @
bacba66c
...
...
@@ -7,13 +7,11 @@ package chequebook
import
(
"bytes"
"errors"
"fmt"
"math/big"
"strings"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethersphere/bee/pkg/settlement/swap/transaction"
"github.com/ethersphere/sw3-bindings/v3/simpleswapfactory"
"golang.org/x/net/context"
...
...
@@ -22,6 +20,9 @@ import (
var
(
ErrInvalidFactory
=
errors
.
New
(
"not a valid factory contract"
)
ErrNotDeployedByFactory
=
errors
.
New
(
"chequebook not deployed by factory"
)
factoryABI
=
transaction
.
ParseABIUnchecked
(
simpleswapfactory
.
SimpleSwapFactoryABI
)
simpleSwapDeployedEventType
=
factoryABI
.
Events
[
"SimpleSwapDeployed"
]
)
// Factory is the main interface for interacting with the chequebook factory.
...
...
@@ -43,17 +44,15 @@ type factory struct {
transactionService
transaction
.
Service
address
common
.
Address
ABI
abi
.
ABI
instance
SimpleSwapFactoryBinding
}
type
simpleSwapDeployedEvent
struct
{
ContractAddress
common
.
Address
}
// NewFactory creates a new factory service for the provided factory contract.
func
NewFactory
(
backend
transaction
.
Backend
,
transactionService
transaction
.
Service
,
address
common
.
Address
,
simpleSwapFactoryBindingFunc
SimpleSwapFactoryBindingFunc
)
(
Factory
,
error
)
{
ABI
,
err
:=
abi
.
JSON
(
strings
.
NewReader
(
simpleswapfactory
.
SimpleSwapFactoryABI
))
if
err
!=
nil
{
return
nil
,
err
}
instance
,
err
:=
simpleSwapFactoryBindingFunc
(
address
,
backend
)
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -63,14 +62,13 @@ func NewFactory(backend transaction.Backend, transactionService transaction.Serv
backend
:
backend
,
transactionService
:
transactionService
,
address
:
address
,
ABI
:
ABI
,
instance
:
instance
,
},
nil
}
// Deploy deploys a new chequebook and returns once the transaction has been submitted.
func
(
c
*
factory
)
Deploy
(
ctx
context
.
Context
,
issuer
common
.
Address
,
defaultHardDepositTimeoutDuration
*
big
.
Int
)
(
common
.
Hash
,
error
)
{
callData
,
err
:=
c
.
ABI
.
Pack
(
"deploySimpleSwap"
,
issuer
,
big
.
NewInt
(
0
)
.
Set
(
defaultHardDepositTimeoutDuration
))
callData
,
err
:=
factory
ABI
.
Pack
(
"deploySimpleSwap"
,
issuer
,
big
.
NewInt
(
0
)
.
Set
(
defaultHardDepositTimeoutDuration
))
if
err
!=
nil
{
return
common
.
Hash
{},
err
}
...
...
@@ -98,32 +96,13 @@ func (c *factory) WaitDeployed(ctx context.Context, txHash common.Hash) (common.
return
common
.
Address
{},
err
}
chequebookAddress
,
err
:=
c
.
parseDeployReceipt
(
receipt
)
var
event
simpleSwapDeployedEvent
err
=
transaction
.
FindSingleEvent
(
&
factoryABI
,
receipt
,
c
.
address
,
simpleSwapDeployedEventType
,
&
event
)
if
err
!=
nil
{
return
common
.
Address
{},
err
return
common
.
Address
{},
fmt
.
Errorf
(
"contract deployment failed: %w"
,
err
)
}
return
chequebookAddress
,
nil
}
// parseDeployReceipt parses the address of the deployed chequebook from the receipt.
func
(
c
*
factory
)
parseDeployReceipt
(
receipt
*
types
.
Receipt
)
(
address
common
.
Address
,
err
error
)
{
if
receipt
.
Status
!=
1
{
return
common
.
Address
{},
transaction
.
ErrTransactionReverted
}
for
_
,
log
:=
range
receipt
.
Logs
{
if
log
.
Address
!=
c
.
address
{
continue
}
if
event
,
err
:=
c
.
instance
.
ParseSimpleSwapDeployed
(
*
log
);
err
==
nil
{
address
=
event
.
ContractAddress
break
}
}
if
(
address
==
common
.
Address
{})
{
return
common
.
Address
{},
errors
.
New
(
"contract deployment failed"
)
}
return
address
,
nil
return
event
.
ContractAddress
,
nil
}
// VerifyBytecode checks that the factory is valid.
...
...
pkg/settlement/swap/chequebook/factory_test.go
View file @
bacba66c
...
...
@@ -5,7 +5,6 @@
package
chequebook_test
import
(
"bytes"
"context"
"errors"
"math/big"
...
...
@@ -21,6 +20,11 @@ import (
"github.com/ethersphere/sw3-bindings/v3/simpleswapfactory"
)
var
(
factoryABI
=
transaction
.
ParseABIUnchecked
(
simpleswapfactory
.
SimpleSwapFactoryABI
)
simpleSwapDeployedEvent
=
factoryABI
.
Events
[
"SimpleSwapDeployed"
]
)
func
newTestFactory
(
t
*
testing
.
T
,
factoryAddress
common
.
Address
,
backend
transaction
.
Backend
,
transactionService
transaction
.
Service
,
simpleSwapFactoryBinding
chequebook
.
SimpleSwapFactoryBinding
)
(
chequebook
.
Factory
,
error
)
{
return
chequebook
.
NewFactory
(
backend
,
transactionService
,
factoryAddress
,
func
(
addr
common
.
Address
,
b
bind
.
ContractBackend
)
(
chequebook
.
SimpleSwapFactoryBinding
,
error
)
{
...
...
@@ -181,7 +185,6 @@ func TestFactoryDeploy(t *testing.T) {
defaultTimeout
:=
big
.
NewInt
(
1
)
deployTransactionHash
:=
common
.
HexToHash
(
"0xffff"
)
deployAddress
:=
common
.
HexToAddress
(
"0xdddd"
)
logData
:=
common
.
Hex2Bytes
(
"0xcccc"
)
factory
,
err
:=
newTestFactory
(
t
,
factoryAddress
,
...
...
@@ -200,6 +203,10 @@ func TestFactoryDeploy(t *testing.T) {
if
txHash
!=
deployTransactionHash
{
t
.
Fatalf
(
"waiting for wrong transaction. wanted %x, got %x"
,
deployTransactionHash
,
txHash
)
}
logData
,
err
:=
simpleSwapDeployedEvent
.
Inputs
.
NonIndexed
()
.
Pack
(
deployAddress
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
return
&
types
.
Receipt
{
Status
:
1
,
Logs
:
[]
*
types
.
Log
{
...
...
@@ -208,22 +215,15 @@ func TestFactoryDeploy(t *testing.T) {
},
{
Address
:
factoryAddress
,
Topics
:
[]
common
.
Hash
{
simpleSwapDeployedEvent
.
ID
},
Data
:
logData
,
},
},
},
nil
}),
),
&
simpleSwapFactoryBindingMock
{
parseSimpleSwapDeployed
:
func
(
log
types
.
Log
)
(
*
simpleswapfactory
.
SimpleSwapFactorySimpleSwapDeployed
,
error
)
{
if
!
bytes
.
Equal
(
log
.
Data
,
logData
)
{
t
.
Fatal
(
"trying to parse wrong log"
)
}
return
&
simpleswapfactory
.
SimpleSwapFactorySimpleSwapDeployed
{
ContractAddress
:
deployAddress
,
},
nil
},
})
nil
,
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
pkg/settlement/swap/transaction/backend.go
View file @
bacba66c
...
...
@@ -6,9 +6,12 @@ package transaction
import
(
"context"
"fmt"
"math/big"
"strings"
"time"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
...
...
@@ -65,3 +68,12 @@ func WaitSynced(ctx context.Context, backend Backend, maxDelay time.Duration) er
}
}
}
// ParseABIUnchecked will parse a valid json abi. Only use this with string constants known to be correct.
func
ParseABIUnchecked
(
json
string
)
abi
.
ABI
{
cabi
,
err
:=
abi
.
JSON
(
strings
.
NewReader
(
json
))
if
err
!=
nil
{
panic
(
fmt
.
Sprintf
(
"error creating ABI for contract: %v"
,
err
))
}
return
cabi
}
pkg/settlement/swap/transaction/event.go
0 → 100644
View file @
bacba66c
// Copyright 2021 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
transaction
import
(
"errors"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
var
(
ErrEventNotFound
=
errors
.
New
(
"event not found"
)
ErrNoTopic
=
errors
.
New
(
"no topic"
)
)
// ParseEvent will parse the specified abi event from the given log
func
ParseEvent
(
a
*
abi
.
ABI
,
eventName
string
,
c
interface
{},
e
types
.
Log
)
error
{
if
len
(
e
.
Topics
)
==
0
{
return
ErrNoTopic
}
if
len
(
e
.
Data
)
>
0
{
if
err
:=
a
.
UnpackIntoInterface
(
c
,
eventName
,
e
.
Data
);
err
!=
nil
{
return
err
}
}
var
indexed
abi
.
Arguments
for
_
,
arg
:=
range
a
.
Events
[
eventName
]
.
Inputs
{
if
arg
.
Indexed
{
indexed
=
append
(
indexed
,
arg
)
}
}
return
abi
.
ParseTopics
(
c
,
indexed
,
e
.
Topics
[
1
:
])
}
// FindSingleEvent will find the first event of the given kind.
func
FindSingleEvent
(
abi
*
abi
.
ABI
,
receipt
*
types
.
Receipt
,
contractAddress
common
.
Address
,
event
abi
.
Event
,
out
interface
{})
error
{
if
receipt
.
Status
!=
1
{
return
ErrTransactionReverted
}
for
_
,
log
:=
range
receipt
.
Logs
{
if
log
.
Address
!=
contractAddress
{
continue
}
if
len
(
log
.
Topics
)
==
0
{
continue
}
if
log
.
Topics
[
0
]
!=
event
.
ID
{
continue
}
return
ParseEvent
(
abi
,
event
.
Name
,
out
,
*
log
)
}
return
ErrEventNotFound
}
pkg/settlement/swap/transaction/event_test.go
0 → 100644
View file @
bacba66c
// Copyright 2021 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
transaction_test
import
(
"errors"
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethersphere/bee/pkg/settlement/swap/transaction"
"github.com/ethersphere/sw3-bindings/v3/simpleswapfactory"
)
var
(
erc20ABI
=
transaction
.
ParseABIUnchecked
(
simpleswapfactory
.
ERC20ABI
)
)
type
transferEvent
struct
{
From
common
.
Address
To
common
.
Address
Value
*
big
.
Int
}
func
newTransferLog
(
address
common
.
Address
,
from
common
.
Address
,
to
common
.
Address
,
value
*
big
.
Int
)
*
types
.
Log
{
return
&
types
.
Log
{
Topics
:
[]
common
.
Hash
{
erc20ABI
.
Events
[
"Transfer"
]
.
ID
,
from
.
Hash
(),
to
.
Hash
(),
},
Data
:
value
.
FillBytes
(
make
([]
byte
,
32
)),
Address
:
address
,
}
}
func
TestParseEvent
(
t
*
testing
.
T
)
{
from
:=
common
.
HexToAddress
(
"00"
)
to
:=
common
.
HexToAddress
(
"01"
)
value
:=
big
.
NewInt
(
0
)
t
.
Run
(
"ok"
,
func
(
t
*
testing
.
T
)
{
var
event
transferEvent
err
:=
transaction
.
ParseEvent
(
&
erc20ABI
,
"Transfer"
,
&
event
,
*
newTransferLog
(
common
.
Address
{},
from
,
to
,
value
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
event
.
From
!=
from
{
t
.
Fatalf
(
"parsed wrong from. wanted %x, got %x"
,
from
,
event
.
From
)
}
if
event
.
To
!=
to
{
t
.
Fatalf
(
"parsed wrong to. wanted %x, got %x"
,
to
,
event
.
To
)
}
if
value
.
Cmp
(
event
.
Value
)
!=
0
{
t
.
Fatalf
(
"parsed wrong value. wanted %d, got %d"
,
value
,
event
.
Value
)
}
})
t
.
Run
(
"no topic"
,
func
(
t
*
testing
.
T
)
{
var
event
transferEvent
err
:=
transaction
.
ParseEvent
(
&
erc20ABI
,
"Transfer"
,
&
event
,
types
.
Log
{
Topics
:
[]
common
.
Hash
{},
})
if
!
errors
.
Is
(
err
,
transaction
.
ErrNoTopic
)
{
t
.
Fatalf
(
"expected error %v, got %v"
,
transaction
.
ErrNoTopic
,
err
)
}
})
}
func
TestFindSingleEvent
(
t
*
testing
.
T
)
{
contractAddress
:=
common
.
HexToAddress
(
"abcd"
)
from
:=
common
.
HexToAddress
(
"00"
)
to
:=
common
.
HexToAddress
(
"01"
)
value
:=
big
.
NewInt
(
0
)
t
.
Run
(
"ok"
,
func
(
t
*
testing
.
T
)
{
var
event
transferEvent
err
:=
transaction
.
FindSingleEvent
(
&
erc20ABI
,
&
types
.
Receipt
{
Logs
:
[]
*
types
.
Log
{
newTransferLog
(
from
,
to
,
from
,
value
),
// event from different contract
{
Topics
:
[]
common
.
Hash
{{}},
Address
:
contractAddress
},
// different event from same contract
newTransferLog
(
contractAddress
,
from
,
to
,
value
),
},
Status
:
1
,
},
contractAddress
,
erc20ABI
.
Events
[
"Transfer"
],
&
event
,
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
event
.
From
!=
from
{
t
.
Fatalf
(
"parsed wrong from. wanted %x, got %x"
,
from
,
event
.
From
)
}
if
event
.
To
!=
to
{
t
.
Fatalf
(
"parsed wrong to. wanted %x, got %x"
,
to
,
event
.
To
)
}
if
value
.
Cmp
(
event
.
Value
)
!=
0
{
t
.
Fatalf
(
"parsed wrong value. wanted %d, got %d"
,
value
,
event
.
Value
)
}
})
t
.
Run
(
"not found"
,
func
(
t
*
testing
.
T
)
{
var
event
transferEvent
err
:=
transaction
.
FindSingleEvent
(
&
erc20ABI
,
&
types
.
Receipt
{
Logs
:
[]
*
types
.
Log
{
newTransferLog
(
from
,
to
,
from
,
value
),
// event from different contract
{
Topics
:
[]
common
.
Hash
{{}},
Address
:
contractAddress
},
// different event from same contract
},
Status
:
1
,
},
contractAddress
,
erc20ABI
.
Events
[
"Transfer"
],
&
event
,
)
if
!
errors
.
Is
(
err
,
transaction
.
ErrEventNotFound
)
{
t
.
Fatalf
(
"wanted error %v, got %v"
,
transaction
.
ErrEventNotFound
,
err
)
}
})
t
.
Run
(
"Reverted"
,
func
(
t
*
testing
.
T
)
{
var
event
transferEvent
err
:=
transaction
.
FindSingleEvent
(
&
erc20ABI
,
&
types
.
Receipt
{
Status
:
0
},
contractAddress
,
erc20ABI
.
Events
[
"Transfer"
],
&
event
,
)
if
!
errors
.
Is
(
err
,
transaction
.
ErrTransactionReverted
)
{
t
.
Fatalf
(
"wanted error %v, got %v"
,
transaction
.
ErrTransactionReverted
,
err
)
}
})
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment