Skip to content

Commit

Permalink
Merge pull request #131 from ElrondNetwork/new-erc20-address
Browse files Browse the repository at this point in the history
Safe contract balance in ERC20 instead of bridge address
  • Loading branch information
iulianpascalau authored Nov 15, 2021
2 parents a92e58a + 650556a commit 84d8de2
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 82 deletions.
1 change: 1 addition & 0 deletions bridge/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type ElrondGasMapConfig struct {
type EthereumConfig struct {
NetworkAddress string
BridgeAddress string
SafeContractAddress string
PrivateKeyFile string
IntervalToResendTxsInSeconds uint64
GasLimit uint64
Expand Down
88 changes: 48 additions & 40 deletions bridge/eth/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,30 +32,30 @@ const (
)

type client struct {
clientWrapper ClientWrapper
addressConverter elrondCore.PubkeyConverter
privateKey *ecdsa.PrivateKey
publicKey *ecdsa.PublicKey
broadcaster bridge.Broadcaster
mapper bridge.Mapper
gasLimit uint64
log logger.Logger
gasHandler bridge.GasHandler
address common.Address
mutErc20Contracts sync.RWMutex
erc20Contracts map[common.Address]Erc20Contract
bridgeAddress common.Address
clientWrapper ClientWrapper
addressConverter elrondCore.PubkeyConverter
privateKey *ecdsa.PrivateKey
publicKey *ecdsa.PublicKey
broadcaster bridge.Broadcaster
mapper bridge.Mapper
gasLimit uint64
log logger.Logger
gasHandler bridge.GasHandler
address common.Address
mutErc20Contracts sync.RWMutex
erc20Contracts map[common.Address]Erc20Contract
safeContractAddress common.Address
}

// ArgsClient is the DTO used in the client constructor
type ArgsClient struct {
Config bridge.EthereumConfig
Broadcaster bridge.Broadcaster
Mapper bridge.Mapper
GasHandler bridge.GasHandler
ClientWrapper ClientWrapper
Erc20Contracts map[common.Address]Erc20Contract
BridgeAddress common.Address
Config bridge.EthereumConfig
Broadcaster bridge.Broadcaster
Mapper bridge.Mapper
GasHandler bridge.GasHandler
ClientWrapper ClientWrapper
Erc20Contracts map[common.Address]Erc20Contract
SafeContractAddress common.Address
}

// NewClient creates a new Ethereum client instance
Expand Down Expand Up @@ -83,24 +83,26 @@ func NewClient(args ArgsClient) (*client, error) {
}

c := &client{
clientWrapper: args.ClientWrapper,
gasLimit: args.Config.GasLimit,
privateKey: privateKey,
publicKey: publicKeyECDSA,
broadcaster: args.Broadcaster,
mapper: args.Mapper,
log: log,
gasHandler: args.GasHandler,
erc20Contracts: args.Erc20Contracts,
bridgeAddress: args.BridgeAddress,
clientWrapper: args.ClientWrapper,
gasLimit: args.Config.GasLimit,
privateKey: privateKey,
publicKey: publicKeyECDSA,
broadcaster: args.Broadcaster,
mapper: args.Mapper,
log: log,
gasHandler: args.GasHandler,
erc20Contracts: args.Erc20Contracts,
safeContractAddress: args.SafeContractAddress,
}
c.addressConverter, err = pubkeyConverter.NewBech32PubkeyConverter(addressLength, log)
if err != nil {
return nil, err
}

c.address = crypto.PubkeyToAddress(*publicKeyECDSA)
log.Info("Ethereum: NewClient", "relayer address", c.address, "bridge address", c.bridgeAddress)
log.Info("Ethereum: NewClient",
"relayer address", c.address.String(),
"safe contract address", c.safeContractAddress.String())

c.retrieveAllCurrentErc20Balances()

Expand Down Expand Up @@ -133,8 +135,8 @@ func checkArgs(args ArgsClient) error {
}

emptyAddress := common.Address{}
if args.BridgeAddress == emptyAddress {
return ErrEmptyBridgeAddress
if args.SafeContractAddress == emptyAddress {
return fmt.Errorf("%w for SafeContractAddress", ErrEmptyBridgeAddress)
}

return nil
Expand All @@ -145,9 +147,12 @@ func (c *client) retrieveAllCurrentErc20Balances() {

for addr, contractInstance := range c.erc20Contracts {
ctx, cancel := context.WithTimeout(context.Background(), maxTimeToWaitForInitialBalanceFetch)
val, err := contractInstance.BalanceOf(ctx, c.bridgeAddress)
val, err := contractInstance.BalanceOf(ctx, c.safeContractAddress)
if err != nil {
c.log.Warn("failed to fetch initial ERC20 balance", "address", "err", err)
c.log.Warn("failed to fetch initial ERC20 balance",
"ERC20 token", addr.String(),
"address", c.safeContractAddress.String(),
"err", err)
val = big.NewInt(0)
}

Expand Down Expand Up @@ -412,18 +417,21 @@ func (c *client) checkCumulatedTransfers(ctx context.Context, transfers map[comm
return fmt.Errorf("%w for %s", ErrMissingErc20ContractDefinition, addr.String())
}

existingBalance, err := contractInstance.BalanceOf(ctx, c.bridgeAddress)
existingBalance, err := contractInstance.BalanceOf(ctx, c.safeContractAddress)
if err != nil {
return fmt.Errorf("%w for %s", err, addr.String())
}

if value.Cmp(existingBalance) > 0 {
return fmt.Errorf("%w, existing: %s, required: %s for %s",
ErrInsufficientErc20Balance, existingBalance.String(), value.String(), addr.String())
return fmt.Errorf("%w, existing: %s, required: %s for ERC20 token %s and address %s",
ErrInsufficientErc20Balance, existingBalance.String(), value.String(), addr.String(), c.safeContractAddress.String())
}

c.log.Debug("checked ERC20 balance", "address", addr.String(),
"existing balance", existingBalance.String(), "needed", value.String())
c.log.Debug("checked ERC20 balance",
"ERC20 token", addr.String(),
"address", c.safeContractAddress.String(),
"existing balance", existingBalance.String(),
"needed", value.String())
}

return nil
Expand Down
36 changes: 18 additions & 18 deletions bridge/eth/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,11 +359,11 @@ func TestExecute(t *testing.T) {
blockNonce := 4321
executeTransferCalled := false

bridgeAddress := testsCommon.CreateRandomEthereumAddress()
safeContractAddress := testsCommon.CreateRandomEthereumAddress()
erc20Contracts := map[common.Address]Erc20Contract{
erc20Address: &mockInteractors.Erc20ContractStub{
BalanceOfCalled: func(ctx context.Context, account common.Address) (*big.Int, error) {
require.Equal(t, account, bridgeAddress)
require.Equal(t, account, safeContractAddress)
return big.NewInt(10001), nil
},
},
Expand All @@ -386,13 +386,13 @@ func TestExecute(t *testing.T) {
},
}
c := client{
clientWrapper: clientWrapper,
privateKey: privateKey(t),
publicKey: publicKey(t),
broadcaster: &testsCommon.BroadcasterStub{},
mapper: mapper,
erc20Contracts: erc20Contracts,
bridgeAddress: bridgeAddress,
clientWrapper: clientWrapper,
privateKey: privateKey(t),
publicKey: publicKey(t),
broadcaster: &testsCommon.BroadcasterStub{},
mapper: mapper,
erc20Contracts: erc20Contracts,
safeContractAddress: safeContractAddress,
gasHandler: &testsCommon.GasHandlerStub{
GetCurrentGasPriceCalled: func() (*big.Int, error) {
return big.NewInt(int64(gasPrice)), nil
Expand Down Expand Up @@ -455,11 +455,11 @@ func TestExecute(t *testing.T) {
blockNonce := 4321
executeTransferCalled := false

bridgeAddress := testsCommon.CreateRandomEthereumAddress()
safeContractAddress := testsCommon.CreateRandomEthereumAddress()
erc20Contracts := map[common.Address]Erc20Contract{
erc20Address: &mockInteractors.Erc20ContractStub{
BalanceOfCalled: func(ctx context.Context, account common.Address) (*big.Int, error) {
require.Equal(t, account, bridgeAddress)
require.Equal(t, account, safeContractAddress)
return big.NewInt(10002), nil
},
},
Expand All @@ -482,13 +482,13 @@ func TestExecute(t *testing.T) {
},
}
c := client{
clientWrapper: clientWrapper,
privateKey: privateKey(t),
publicKey: publicKey(t),
broadcaster: &testsCommon.BroadcasterStub{},
mapper: mapper,
erc20Contracts: erc20Contracts,
bridgeAddress: bridgeAddress,
clientWrapper: clientWrapper,
privateKey: privateKey(t),
publicKey: publicKey(t),
broadcaster: &testsCommon.BroadcasterStub{},
mapper: mapper,
erc20Contracts: erc20Contracts,
safeContractAddress: safeContractAddress,
gasHandler: &testsCommon.GasHandlerStub{
GetCurrentGasPriceCalled: func() (*big.Int, error) {
return big.NewInt(int64(gasPrice)), nil
Expand Down
3 changes: 2 additions & 1 deletion cmd/bridge/config/config.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
[Eth]
NetworkAddress = "http://127.0.0.1:8545" # a network address
BridgeAddress = "3009d97FfeD62E57d444e552A9eDF9Ee6Bc8644c" # the eth address for the bridge contract
SafeContractAddress = "A6504Cc508889bbDBd4B748aFf6EA6b5D0d2684c"
PrivateKeyFile = "config/ethereum.sk" # the path to the file containing the relayer eth private key
GasLimit = 500000
ERC20Contracts = ["64a8bfab8e7ac5d5a3561d95b504542e9e29ce24", "4d75EF4411cda0E0C257383054Fe68febB993D37"]
ERC20Contracts = ["d1135C0307CEB01FD4728db8e5B8D38fbf984F9a"]
[Eth.GasStation]
Enabled = true
URL = "https://ethgasstation.info/api/ethgasAPI.json?" # gas station URL. Suggestion to provide the api-key here
Expand Down
1 change: 0 additions & 1 deletion cmd/bridge/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,6 @@ func startRelay(ctx *cli.Context, version string) error {
EthInstance: ethInstance,
Messenger: messenger,
Erc20Contracts: erc20Contracts,
BridgeEthAddress: bridgeEthAddress,
EthClientStatusHandler: ethClientStatusHandler,
StatusStorer: statusStorer,
}
Expand Down
6 changes: 3 additions & 3 deletions integrationTests/relayers/elrondToEth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ func TestRelayersShouldExecuteTransferFromElrondToEth(t *testing.T) {
numTransactions := 2
deposits, tokensAddresses, erc20Map := createTransactions(numTransactions)

bridgeEthAddress := testsCommon.CreateRandomEthereumAddress()
safeContractEthAddress := testsCommon.CreateRandomEthereumAddress()
erc20Contracts := make(map[common.Address]eth.Erc20Contract)
for addr, val := range erc20Map {
value := big.NewInt(0).Set(val)
erc20Contracts[addr] = &mockInteractors.Erc20ContractStub{
BalanceOfCalled: func(ctx context.Context, account common.Address) (*big.Int, error) {
if account == bridgeEthAddress {
if account == safeContractEthAddress {
return value, nil
}

Expand Down Expand Up @@ -80,8 +80,8 @@ func TestRelayersShouldExecuteTransferFromElrondToEth(t *testing.T) {

for i := 0; i < numRelayers; i++ {
argsRelay := mock.CreateMockRelayArgs("elrond <-> eth", i, messengers[i], elrondChainMock, ethereumChainMock)
argsRelay.Configs.GeneralConfig.Eth.SafeContractAddress = safeContractEthAddress.Hex()
argsRelay.Erc20Contracts = erc20Contracts
argsRelay.BridgeEthAddress = bridgeEthAddress
r, err := relay.NewRelay(argsRelay)
require.Nil(t, err)

Expand Down
6 changes: 3 additions & 3 deletions integrationTests/relayers/ethToElrond_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func TestRelayersShouldExecuteTransferFromEthToElrond(t *testing.T) {
t.Skip("this is not a short test")
}

bridgeEthAddress := testsCommon.CreateRandomEthereumAddress()
safeContractEthAddress := testsCommon.CreateRandomEthereumAddress()
token1Erc20 := testsCommon.CreateRandomEthereumAddress()
ticker1 := "tck-000001"

Expand All @@ -50,7 +50,7 @@ func TestRelayersShouldExecuteTransferFromEthToElrond(t *testing.T) {
for i, token := range tokens {
erc20Contracts[token] = &mockInteractors.Erc20ContractStub{
BalanceOfCalled: func(ctx context.Context, account common.Address) (*big.Int, error) {
if account == bridgeEthAddress {
if account == safeContractEthAddress {
return availableBalances[i], nil
}

Expand Down Expand Up @@ -113,8 +113,8 @@ func TestRelayersShouldExecuteTransferFromEthToElrond(t *testing.T) {

for i := 0; i < numRelayers; i++ {
argsRelay := createMockRelayArgs(i, messengers[i], elrondChainMock, ethereumChainMock)
argsRelay.Configs.GeneralConfig.Eth.SafeContractAddress = safeContractEthAddress.Hex()
argsRelay.Erc20Contracts = erc20Contracts
argsRelay.BridgeEthAddress = bridgeEthAddress
r, err := relay.NewRelay(argsRelay)
require.Nil(t, err)

Expand Down
16 changes: 8 additions & 8 deletions relay/relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ type ArgsRelayer struct {
EthInstance wrappers.BridgeContract
Messenger p2p.NetMessenger
Erc20Contracts map[common.Address]eth.Erc20Contract
BridgeEthAddress common.Address
EthClientStatusHandler core.StatusHandler
StatusStorer core.Storer
}
Expand Down Expand Up @@ -187,14 +186,15 @@ func NewRelay(args ArgsRelayer) (*Relay, error) {
return nil, err
}

safeContractAddress := common.HexToAddress(cfgs.Eth.SafeContractAddress)
argsClient := eth.ArgsClient{
Config: cfgs.Eth,
Broadcaster: relay,
Mapper: elrondBridge,
GasHandler: gs,
ClientWrapper: ethClientWrapper,
Erc20Contracts: args.Erc20Contracts,
BridgeAddress: args.BridgeEthAddress,
Config: cfgs.Eth,
Broadcaster: relay,
Mapper: elrondBridge,
GasHandler: gs,
ClientWrapper: ethClientWrapper,
Erc20Contracts: args.Erc20Contracts,
SafeContractAddress: safeContractAddress,
}
ethBridge, err := eth.NewClient(argsClient)
if err != nil {
Expand Down
15 changes: 7 additions & 8 deletions relay/relay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func TestNewRelay(t *testing.T) {
cfg := &config.Config{
Eth: bridge.EthereumConfig{
NetworkAddress: "http://127.0.0.1:8545",
BridgeAddress: "5DdDe022a65F8063eE9adaC54F359CBF46166068",
SafeContractAddress: "5DdDe022a65F8063eE9adaC54F359CBF46166068",
PrivateKeyFile: "testdata/grace.sk",
IntervalToResendTxsInSeconds: 0,
GasLimit: 0,
Expand Down Expand Up @@ -80,13 +80,12 @@ func TestNewRelay(t *testing.T) {
require.Nil(t, err)

args := ArgsRelayer{
Configs: configs,
Name: "name",
Proxy: blockchain.NewElrondProxy(cfg.Elrond.NetworkAddress, nil),
EthClient: ethClient,
EthInstance: ethInstance,
Messenger: &p2pMocks.MessengerStub{},
BridgeEthAddress: testsCommon.CreateRandomEthereumAddress(),
Configs: configs,
Name: "name",
Proxy: blockchain.NewElrondProxy(cfg.Elrond.NetworkAddress, nil),
EthClient: ethClient,
EthInstance: ethInstance,
Messenger: &p2pMocks.MessengerStub{},
Erc20Contracts: map[ethCommon.Address]eth.Erc20Contract{
testsCommon.CreateRandomEthereumAddress(): &mockInteractors.Erc20ContractStub{},
},
Expand Down

0 comments on commit 84d8de2

Please sign in to comment.