Skip to content

Commit

Permalink
Merge pull request #282 from multiversx/MX-15083
Browse files Browse the repository at this point in the history
MX-15083: fix mxClientDataGetter
  • Loading branch information
dragos-rebegea authored Jan 24, 2024
2 parents 08fc1b0 + ad67f12 commit 11ef8b9
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 19 deletions.
15 changes: 14 additions & 1 deletion clients/multiversx/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type ClientArgs struct {
Log logger.Logger
RelayerPrivateKey crypto.PrivateKey
MultisigContractAddress core.AddressHandler
SafeContractAddress core.AddressHandler
IntervalToResendTxsInSeconds uint64
TokensMapper TokensMapper
RoleProvider roleProvider
Expand All @@ -55,6 +56,7 @@ type client struct {
relayerPublicKey crypto.PublicKey
relayerAddress core.AddressHandler
multisigContractAddress core.AddressHandler
safeContractAddress core.AddressHandler
log logger.Logger
gasMapConfig config.MultiversXGasMapConfig
addressPublicKeyConverter bridgeCore.AddressConverter
Expand Down Expand Up @@ -97,6 +99,7 @@ func NewClient(args ClientArgs) (*client, error) {

argsMXClientDataGetter := ArgsMXClientDataGetter{
MultisigContractAddress: args.MultisigContractAddress,
SafeContractAddress: args.SafeContractAddress,
RelayerAddress: relayerAddress,
Proxy: args.Proxy,
Log: bridgeCore.NewLoggerWithIdentifier(logger.GetOrCreate(multiversXDataGetterLogId), multiversXDataGetterLogId),
Expand All @@ -116,6 +119,11 @@ func NewClient(args ClientArgs) (*client, error) {
return nil, fmt.Errorf("%w for %x", err, args.MultisigContractAddress.AddressBytes())

Check warning on line 119 in clients/multiversx/client.go

View check run for this annotation

Codecov / codecov/patch

clients/multiversx/client.go#L119

Added line #L119 was not covered by tests
}

bech23SafeAddress, err := args.SafeContractAddress.AddressAsBech32String()
if err != nil {
return nil, fmt.Errorf("%w for %x", err, args.SafeContractAddress.AddressBytes())

Check warning on line 124 in clients/multiversx/client.go

View check run for this annotation

Codecov / codecov/patch

clients/multiversx/client.go#L124

Added line #L124 was not covered by tests
}

c := &client{
txHandler: &transactionHandler{
proxy: args.Proxy,
Expand All @@ -130,6 +138,7 @@ func NewClient(args ClientArgs) (*client, error) {
relayerPublicKey: publicKey,
relayerAddress: relayerAddress,
multisigContractAddress: args.MultisigContractAddress,
safeContractAddress: args.SafeContractAddress,
log: args.Log,
gasMapConfig: args.GasMapConfig,
addressPublicKeyConverter: addressConverter,
Expand All @@ -141,7 +150,8 @@ func NewClient(args ClientArgs) (*client, error) {
bech32RelayerAddress, _ := relayerAddress.AddressAsBech32String()
c.log.Info("NewMultiversXClient",
"relayer address", bech32RelayerAddress,
"safe contract address", bech23MultisigAddress)
"multisig contract address", bech23MultisigAddress,
"safe contract address", bech23SafeAddress)

return c, nil
}
Expand All @@ -156,6 +166,9 @@ func checkArgs(args ClientArgs) error {
if check.IfNil(args.MultisigContractAddress) {
return fmt.Errorf("%w for the MultisigContractAddress argument", errNilAddressHandler)
}
if check.IfNil(args.SafeContractAddress) {
return fmt.Errorf("%w for the SafeContractAddress argument", errNilAddressHandler)
}
if check.IfNil(args.Log) {
return clients.ErrNilLogger
}
Expand Down
13 changes: 13 additions & 0 deletions clients/multiversx/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ var pausedBytes = []byte{1}
func createMockClientArgs() ClientArgs {
privateKey, _ := testKeyGen.PrivateKeyFromByteArray(bytes.Repeat([]byte{1}, 32))
multisigContractAddress, _ := data.NewAddressFromBech32String("erd1qqqqqqqqqqqqqpgqzyuaqg3dl7rqlkudrsnm5ek0j3a97qevd8sszj0glf")
safeContractAddress, _ := data.NewAddressFromBech32String("erd1qqqqqqqqqqqqqpgqtvnswnzxxz8susupesys0hvg7q2z5nawrcjq06qdus")

return ClientArgs{
GasMapConfig: config.MultiversXGasMapConfig{
Expand All @@ -52,6 +53,7 @@ func createMockClientArgs() ClientArgs {
Log: logger.GetOrCreate("test"),
RelayerPrivateKey: privateKey,
MultisigContractAddress: multisigContractAddress,
SafeContractAddress: safeContractAddress,
IntervalToResendTxsInSeconds: 1,
TokensMapper: &bridgeTests.TokensMapperStub{
ConvertTokenCalled: func(ctx context.Context, sourceBytes []byte) ([]byte, error) {
Expand Down Expand Up @@ -125,6 +127,17 @@ func TestNewClient(t *testing.T) {
require.True(t, check.IfNil(c))
require.True(t, errors.Is(err, errNilAddressHandler))
})
t.Run("nil safe contract address should error", func(t *testing.T) {
t.Parallel()

args := createMockClientArgs()
args.SafeContractAddress = nil

c, err := NewClient(args)

require.True(t, check.IfNil(c))
require.True(t, errors.Is(err, errNilAddressHandler))
})
t.Run("nil logger should error", func(t *testing.T) {
t.Parallel()

Expand Down
46 changes: 28 additions & 18 deletions clients/multiversx/mxClientDataGetter.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ const (
// ArgsMXClientDataGetter is the arguments DTO used in the NewMXClientDataGetter constructor
type ArgsMXClientDataGetter struct {
MultisigContractAddress core.AddressHandler
SafeContractAddress core.AddressHandler
RelayerAddress core.AddressHandler
Proxy Proxy
Log logger.Logger
}

type mxClientDataGetter struct {
multisigContractAddress core.AddressHandler
safeContractAddress core.AddressHandler
bech32MultisigContractAddress string
relayerAddress core.AddressHandler
proxy Proxy
Expand All @@ -70,13 +72,17 @@ func NewMXClientDataGetter(args ArgsMXClientDataGetter) (*mxClientDataGetter, er
if check.IfNil(args.MultisigContractAddress) {
return nil, fmt.Errorf("%w for the MultisigContractAddress argument", errNilAddressHandler)
}
if check.IfNil(args.SafeContractAddress) {
return nil, fmt.Errorf("%w for the SafeContractAddress argument", errNilAddressHandler)
}
bech32Address, err := args.MultisigContractAddress.AddressAsBech32String()
if err != nil {
return nil, fmt.Errorf("%w for %x", err, args.MultisigContractAddress.AddressBytes())

Check warning on line 80 in clients/multiversx/mxClientDataGetter.go

View check run for this annotation

Codecov / codecov/patch

clients/multiversx/mxClientDataGetter.go#L80

Added line #L80 was not covered by tests
}

return &mxClientDataGetter{
multisigContractAddress: args.MultisigContractAddress,
safeContractAddress: args.SafeContractAddress,
bech32MultisigContractAddress: bech32Address,
relayerAddress: args.RelayerAddress,
proxy: args.Proxy,
Expand Down Expand Up @@ -271,21 +277,25 @@ func (dataGetter *mxClientDataGetter) executeQueryBoolFromBuilder(ctx context.Co
return dataGetter.ExecuteQueryReturningBool(ctx, vmValuesRequest)
}

func (dataGetter *mxClientDataGetter) createDefaultVmQueryBuilder() builders.VMQueryBuilder {
func (dataGetter *mxClientDataGetter) createMultisigDefaultVmQueryBuilder() builders.VMQueryBuilder {
return builders.NewVMQueryBuilder().Address(dataGetter.multisigContractAddress).CallerAddress(dataGetter.relayerAddress)
}

func (dataGetter *mxClientDataGetter) createSafeDefaultVmQueryBuilder() builders.VMQueryBuilder {
return builders.NewVMQueryBuilder().Address(dataGetter.safeContractAddress).CallerAddress(dataGetter.relayerAddress)
}

// GetCurrentBatchAsDataBytes will assemble a builder and query the proxy for the current pending batch
func (dataGetter *mxClientDataGetter) GetCurrentBatchAsDataBytes(ctx context.Context) ([][]byte, error) {
builder := dataGetter.createDefaultVmQueryBuilder()
builder := dataGetter.createMultisigDefaultVmQueryBuilder()
builder.Function(getCurrentTxBatchFuncName)

return dataGetter.executeQueryFromBuilder(ctx, builder)
}

// GetTokenIdForErc20Address will assemble a builder and query the proxy for a token id given a specific erc20 address
func (dataGetter *mxClientDataGetter) GetTokenIdForErc20Address(ctx context.Context, erc20Address []byte) ([][]byte, error) {
builder := dataGetter.createDefaultVmQueryBuilder()
builder := dataGetter.createMultisigDefaultVmQueryBuilder()
builder.Function(getTokenIdForErc20AddressFuncName)
builder.ArgBytes(erc20Address)

Expand All @@ -294,7 +304,7 @@ func (dataGetter *mxClientDataGetter) GetTokenIdForErc20Address(ctx context.Cont

// GetERC20AddressForTokenId will assemble a builder and query the proxy for an erc20 address given a specific token id
func (dataGetter *mxClientDataGetter) GetERC20AddressForTokenId(ctx context.Context, tokenId []byte) ([][]byte, error) {
builder := dataGetter.createDefaultVmQueryBuilder()
builder := dataGetter.createMultisigDefaultVmQueryBuilder()
builder.Function(getErc20AddressForTokenIdFuncName)
builder.ArgBytes(tokenId)
return dataGetter.executeQueryFromBuilder(ctx, builder)
Expand All @@ -306,7 +316,7 @@ func (dataGetter *mxClientDataGetter) WasProposedTransfer(ctx context.Context, b
return false, clients.ErrNilBatch
}

builder := dataGetter.createDefaultVmQueryBuilder()
builder := dataGetter.createMultisigDefaultVmQueryBuilder()
builder.Function(wasTransferActionProposedFuncName).ArgInt64(int64(batch.ID))
addBatchInfo(builder, batch)

Expand All @@ -315,7 +325,7 @@ func (dataGetter *mxClientDataGetter) WasProposedTransfer(ctx context.Context, b

// WasExecuted returns true if the provided actionID was executed or not
func (dataGetter *mxClientDataGetter) WasExecuted(ctx context.Context, actionID uint64) (bool, error) {
builder := dataGetter.createDefaultVmQueryBuilder()
builder := dataGetter.createMultisigDefaultVmQueryBuilder()
builder.Function(wasActionExecutedFuncName).ArgInt64(int64(actionID))

return dataGetter.executeQueryBoolFromBuilder(ctx, builder)
Expand All @@ -327,7 +337,7 @@ func (dataGetter *mxClientDataGetter) GetActionIDForProposeTransfer(ctx context.
return 0, clients.ErrNilBatch
}

builder := dataGetter.createDefaultVmQueryBuilder()
builder := dataGetter.createMultisigDefaultVmQueryBuilder()
builder.Function(getActionIdForTransferBatchFuncName).ArgInt64(int64(batch.ID))
addBatchInfo(builder, batch)

Expand All @@ -340,7 +350,7 @@ func (dataGetter *mxClientDataGetter) WasProposedSetStatus(ctx context.Context,
return false, clients.ErrNilBatch
}

builder := dataGetter.createDefaultVmQueryBuilder()
builder := dataGetter.createMultisigDefaultVmQueryBuilder()
builder.Function(wasSetCurrentTransactionBatchStatusActionProposedFuncName).ArgInt64(int64(batch.ID))
for _, stat := range batch.Statuses {
builder.ArgBytes([]byte{stat})
Expand All @@ -351,7 +361,7 @@ func (dataGetter *mxClientDataGetter) WasProposedSetStatus(ctx context.Context,

// GetTransactionsStatuses will return the transactions statuses from the batch ID
func (dataGetter *mxClientDataGetter) GetTransactionsStatuses(ctx context.Context, batchID uint64) ([]byte, error) {
builder := dataGetter.createDefaultVmQueryBuilder()
builder := dataGetter.createMultisigDefaultVmQueryBuilder()
builder.Function(getStatusesAfterExecutionFuncName).ArgInt64(int64(batchID))

values, err := dataGetter.executeQueryFromBuilder(ctx, builder)
Expand Down Expand Up @@ -391,7 +401,7 @@ func (dataGetter *mxClientDataGetter) GetActionIDForSetStatusOnPendingTransfer(c
return 0, clients.ErrNilBatch
}

builder := dataGetter.createDefaultVmQueryBuilder()
builder := dataGetter.createMultisigDefaultVmQueryBuilder()
builder.Function(getActionIdForSetCurrentTransactionBatchStatusFuncName).ArgInt64(int64(batch.ID))
for _, stat := range batch.Statuses {
builder.ArgBytes([]byte{stat})
Expand All @@ -402,59 +412,59 @@ func (dataGetter *mxClientDataGetter) GetActionIDForSetStatusOnPendingTransfer(c

// QuorumReached returns true if the provided action ID reached the set quorum
func (dataGetter *mxClientDataGetter) QuorumReached(ctx context.Context, actionID uint64) (bool, error) {
builder := dataGetter.createDefaultVmQueryBuilder()
builder := dataGetter.createMultisigDefaultVmQueryBuilder()
builder.Function(quorumReachedFuncName).ArgInt64(int64(actionID))

return dataGetter.executeQueryBoolFromBuilder(ctx, builder)
}

// GetLastExecutedEthBatchID returns the last executed Ethereum batch ID
func (dataGetter *mxClientDataGetter) GetLastExecutedEthBatchID(ctx context.Context) (uint64, error) {
builder := dataGetter.createDefaultVmQueryBuilder().Function(getLastExecutedEthBatchIdFuncName)
builder := dataGetter.createMultisigDefaultVmQueryBuilder().Function(getLastExecutedEthBatchIdFuncName)

return dataGetter.executeQueryUint64FromBuilder(ctx, builder)
}

// GetLastExecutedEthTxID returns the last executed Ethereum deposit ID
func (dataGetter *mxClientDataGetter) GetLastExecutedEthTxID(ctx context.Context) (uint64, error) {
builder := dataGetter.createDefaultVmQueryBuilder().Function(getLastExecutedEthTxId)
builder := dataGetter.createMultisigDefaultVmQueryBuilder().Function(getLastExecutedEthTxId)

return dataGetter.executeQueryUint64FromBuilder(ctx, builder)
}

// WasSigned returns true if the action was already signed by the current relayer
func (dataGetter *mxClientDataGetter) WasSigned(ctx context.Context, actionID uint64) (bool, error) {
builder := dataGetter.createDefaultVmQueryBuilder()
builder := dataGetter.createMultisigDefaultVmQueryBuilder()
builder.Function(signedFuncName).ArgAddress(dataGetter.relayerAddress).ArgInt64(int64(actionID))

return dataGetter.executeQueryBoolFromBuilder(ctx, builder)
}

// GetAllStakedRelayers returns all staked relayers defined in MultiversX SC
func (dataGetter *mxClientDataGetter) GetAllStakedRelayers(ctx context.Context) ([][]byte, error) {
builder := dataGetter.createDefaultVmQueryBuilder()
builder := dataGetter.createMultisigDefaultVmQueryBuilder()
builder.Function(getAllStakedRelayersFuncName)

return dataGetter.executeQueryFromBuilder(ctx, builder)
}

// IsPaused returns true if the multisig contract is paused
func (dataGetter *mxClientDataGetter) IsPaused(ctx context.Context) (bool, error) {
builder := dataGetter.createDefaultVmQueryBuilder()
builder := dataGetter.createMultisigDefaultVmQueryBuilder()
builder.Function(isPausedFuncName)

return dataGetter.executeQueryBoolFromBuilder(ctx, builder)
}

func (dataGetter *mxClientDataGetter) isMintBurnAllowed(ctx context.Context, token []byte) (bool, error) {
builder := dataGetter.createDefaultVmQueryBuilder()
builder := dataGetter.createSafeDefaultVmQueryBuilder()
builder.Function(isMintBurnAllowedFuncName).ArgBytes(token)

return dataGetter.executeQueryBoolFromBuilder(ctx, builder)
}

func (dataGetter *mxClientDataGetter) getAccumulatedBurnedTokens(ctx context.Context, token []byte) (*big.Int, error) {
builder := dataGetter.createDefaultVmQueryBuilder()
builder := dataGetter.createSafeDefaultVmQueryBuilder()
builder.Function(getAccumulatedBurnedTokensFuncName).ArgBytes(token)

return dataGetter.executeQueryBigIntFromBuilder(ctx, builder)
Expand Down
77 changes: 77 additions & 0 deletions clients/multiversx/mxClientDataGetter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func createMockArgsMXClientDataGetter() ArgsMXClientDataGetter {
}

args.MultisigContractAddress, _ = data.NewAddressFromBech32String("erd1qqqqqqqqqqqqqpgqzyuaqg3dl7rqlkudrsnm5ek0j3a97qevd8sszj0glf")
args.SafeContractAddress, _ = data.NewAddressFromBech32String("erd1qqqqqqqqqqqqqpgqtvnswnzxxz8susupesys0hvg7q2z5nawrcjq06qdus")
args.RelayerAddress, _ = data.NewAddressFromBech32String("erd1r69gk66fmedhhcg24g2c5kn2f2a5k4kvpr6jfw67dn2lyydd8cfswy6ede")

return args
Expand Down Expand Up @@ -125,6 +126,17 @@ func TestNewMXClientDataGetter(t *testing.T) {
assert.True(t, strings.Contains(err.Error(), "MultisigContractAddress"))
assert.True(t, check.IfNil(dg))
})
t.Run("nil safe contact address", func(t *testing.T) {
t.Parallel()

args := createMockArgsMXClientDataGetter()
args.SafeContractAddress = nil

dg, err := NewMXClientDataGetter(args)
assert.True(t, errors.Is(err, errNilAddressHandler))
assert.True(t, strings.Contains(err.Error(), "SafeContractAddress"))
assert.True(t, check.IfNil(dg))
})
t.Run("nil relayer address", func(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -1378,3 +1390,68 @@ func TestMultiversXClientDataGetter_IsPaused(t *testing.T) {
assert.True(t, result)
assert.True(t, proxyCalled)
}

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

args := createMockArgsMXClientDataGetter()
proxyCalled := false
args.Proxy = &interactors.ProxyStub{
ExecuteVMQueryCalled: func(ctx context.Context, vmRequest *data.VmValueRequest) (*data.VmValuesResponseData, error) {
proxyCalled = true
assert.Equal(t, getBech32Address(args.SafeContractAddress), vmRequest.Address)
assert.Equal(t, getBech32Address(args.RelayerAddress), vmRequest.CallerAddr)
assert.Equal(t, "", vmRequest.CallValue)
assert.Equal(t, isMintBurnAllowedFuncName, vmRequest.FuncName)
assert.Equal(t, []string{"746f6b656e"}, vmRequest.Args)

strResponse := "AQ=="
response, _ := base64.StdEncoding.DecodeString(strResponse)
return &data.VmValuesResponseData{
Data: &vm.VMOutputApi{
ReturnCode: okCodeAfterExecution,
ReturnData: [][]byte{response},
},
}, nil
},
}

dg, _ := NewMXClientDataGetter(args)

result, err := dg.isMintBurnAllowed(context.Background(), []byte("token"))
assert.Nil(t, err)
assert.True(t, result)
assert.True(t, proxyCalled)
}

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

args := createMockArgsMXClientDataGetter()
proxyCalled := false
expectedAccumulatedBurnedTokens := big.NewInt(100)
args.Proxy = &interactors.ProxyStub{
ExecuteVMQueryCalled: func(ctx context.Context, vmRequest *data.VmValueRequest) (*data.VmValuesResponseData, error) {
proxyCalled = true
assert.Equal(t, getBech32Address(args.SafeContractAddress), vmRequest.Address)
assert.Equal(t, getBech32Address(args.RelayerAddress), vmRequest.CallerAddr)
assert.Equal(t, "", vmRequest.CallValue)
assert.Equal(t, getAccumulatedBurnedTokensFuncName, vmRequest.FuncName)
assert.Equal(t, []string{"746f6b656e"}, vmRequest.Args)

return &data.VmValuesResponseData{
Data: &vm.VMOutputApi{
ReturnCode: okCodeAfterExecution,
ReturnData: [][]byte{expectedAccumulatedBurnedTokens.Bytes()},
},
}, nil
},
}

dg, _ := NewMXClientDataGetter(args)

result, err := dg.getAccumulatedBurnedTokens(context.Background(), []byte("token"))
assert.Nil(t, err)
assert.Equal(t, result, expectedAccumulatedBurnedTokens)
assert.True(t, proxyCalled)
}
1 change: 1 addition & 0 deletions cmd/bridge/config/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
[MultiversX]
NetworkAddress = "https://devnet-gateway.multiversx.com" # the network address
MultisigContractAddress = "erd1qqqqqqqqqqqqqpgqzyuaqg3dl7rqlkudrsnm5ek0j3a97qevd8sszj0glf" # the multiversx address for the bridge contract
SafeContractAddress = "erd1qqqqqqqqqqqqqpgqtvnswnzxxz8susupesys0hvg7q2z5nawrcjq06qdus" # the multiversx address for the safe contract
PrivateKeyFile = "keys/multiversx.pem" # the path to the pem file containing the relayer multiversx wallet
IntervalToResendTxsInSeconds = 60 # the time in seconds between nonce reads
MaxRetriesOnQuorumReached = 3
Expand Down
Loading

0 comments on commit 11ef8b9

Please sign in to comment.