From 8451b922955aacc237452be53e23f7bf5c2cfacf Mon Sep 17 00:00:00 2001 From: laisolizq Date: Mon, 28 Sep 2020 17:53:10 +0200 Subject: [PATCH 1/2] Update ethclient contracts & add wdelayer events --- eth/auction.go | 37 ++++++++++-- eth/auction_test.go | 74 ++++++++++++++--------- eth/helpers.go | 63 ++++++++++++++++++++ eth/main_test.go | 24 +++++--- eth/wdelayer.go | 132 ++++++++++++++++++++++++++++++++++++++--- eth/wdelayer_test.go | 137 ++++++++++++++++++++++++++++++------------- 6 files changed, 376 insertions(+), 91 deletions(-) create mode 100644 eth/helpers.go diff --git a/eth/auction.go b/eth/auction.go index 2b7a329..27d07ce 100644 --- a/eth/auction.go +++ b/eth/auction.go @@ -281,10 +281,10 @@ type AuctionClient struct { } // NewAuctionClient creates a new AuctionClient. `tokenAddress` is the address of the HEZ tokens. -func NewAuctionClient(client *EthereumClient, address, tokenAddress ethCommon.Address) *AuctionClient { +func NewAuctionClient(client *EthereumClient, address, tokenAddress ethCommon.Address) (*AuctionClient, error) { contractAbi, err := abi.JSON(strings.NewReader(string(HermezAuctionProtocol.HermezAuctionProtocolABI))) if err != nil { - fmt.Println(err) + return nil, err } return &AuctionClient{ client: client, @@ -292,7 +292,7 @@ func NewAuctionClient(client *EthereumClient, address, tokenAddress ethCommon.Ad tokenAddress: tokenAddress, gasLimit: 1000000, //nolint:gomnd contractAbi: contractAbi, - } + }, nil } // AuctionSetSlotDeadline is the interface to call the smart contract function @@ -841,6 +841,25 @@ func (c *AuctionClient) AuctionClaimHEZ(claimAddress ethCommon.Address) (*types. return tx, nil } +// AuctionForge is the interface to call the smart contract function +func (c *AuctionClient) AuctionForge(forger ethCommon.Address) (*types.Transaction, error) { + var tx *types.Transaction + var err error + if tx, err = c.client.CallAuth( + c.gasLimit, + func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) { + auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec) + if err != nil { + return nil, err + } + return auction.Forge(auth, forger) + }, + ); err != nil { + return nil, fmt.Errorf("Failed forge: %w", err) + } + return tx, nil +} + // AuctionConstants returns the Constants of the Auction Smart Contract func (c *AuctionClient) AuctionConstants() (*AuctionConstants, error) { auctionConstants := new(AuctionConstants) @@ -942,6 +961,7 @@ var ( // AuctionEventsByBlock returns the events in a block that happened in the Auction Smart Contract func (c *AuctionClient) AuctionEventsByBlock(blockNum int64) (*AuctionEvents, *ethCommon.Hash, error) { var auctionEvents AuctionEvents + var blockHash ethCommon.Hash query := ethereum.FilterQuery{ FromBlock: big.NewInt(blockNum), @@ -949,15 +969,20 @@ func (c *AuctionClient) AuctionEventsByBlock(blockNum int64) (*AuctionEvents, *e Addresses: []ethCommon.Address{ c.address, }, - BlockHash: nil, // TODO: Maybe we can put the blockHash here to make sure we get the results from the known block. - Topics: [][]ethCommon.Hash{}, + Topics: [][]ethCommon.Hash{}, } logs, err := c.client.client.FilterLogs(context.TODO(), query) if err != nil { fmt.Println(err) } + if len(logs) > 0 { + blockHash = logs[0].BlockHash + } for _, vLog := range logs { + if vLog.BlockHash != blockHash { + return nil, nil, err + } switch vLog.Topics[0] { case logNewBid: var auxNewBid struct { @@ -1061,5 +1086,5 @@ func (c *AuctionClient) AuctionEventsByBlock(blockNum int64) (*AuctionEvents, *e auctionEvents.HEZClaimed = append(auctionEvents.HEZClaimed, HEZClaimed) } } - return &auctionEvents, nil, nil + return &auctionEvents, &blockHash, nil } diff --git a/eth/auction_test.go b/eth/auction_test.go index d942e82..bb286bb 100644 --- a/eth/auction_test.go +++ b/eth/auction_test.go @@ -1,7 +1,6 @@ package eth import ( - "context" "math/big" "testing" @@ -19,7 +18,8 @@ var allocationRatioConst [3]uint16 = [3]uint16{4000, 4000, 2000} var auctionClient *AuctionClient -var genesisBlock = 91 +//var genesisBlock = 91 +var genesisBlock = 98 var minBidStr = "10000000000000000000" var URL = "http://localhost:3000" @@ -41,7 +41,7 @@ func TestAuctionConstants(t *testing.T) { require.Nil(t, err) assert.Equal(t, auctionConstants.BlocksPerSlot, BLOCKSPERSLOT) // assert.Equal(t, auctionConstants.GenesisBlockNum, GENESISBLOCKNUM) - assert.Equal(t, auctionConstants.HermezRollup, hermezRollupAddressConst) + assert.Equal(t, auctionConstants.HermezRollup, hermezRollupAddressTestConst) assert.Equal(t, auctionConstants.InitialMinimalBidding, INITMINBID) assert.Equal(t, auctionConstants.TokenHEZ, tokenHezAddressConst) } @@ -77,8 +77,8 @@ func TestAuctionSetSlotDeadline(t *testing.T) { slotDeadline, err := auctionClient.AuctionGetSlotDeadline() require.Nil(t, err) assert.Equal(t, newSlotDeadline, slotDeadline) - header, _ := auctionClient.client.client.HeaderByNumber(context.Background(), nil) - auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(header.Number.Int64()) + currentBlockNum, _ := auctionClient.client.EthCurrentBlock() + auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(currentBlockNum) assert.Equal(t, newSlotDeadline, auctionEvents.NewSlotDeadline[0].NewSlotDeadline) } @@ -96,8 +96,8 @@ func TestAuctionSetOpenAuctionSlots(t *testing.T) { openAuctionSlots, err := auctionClient.AuctionGetOpenAuctionSlots() require.Nil(t, err) assert.Equal(t, newOpenAuctionSlots, openAuctionSlots) - header, _ := auctionClient.client.client.HeaderByNumber(context.Background(), nil) - auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(header.Number.Int64()) + currentBlockNum, _ := auctionClient.client.EthCurrentBlock() + auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(currentBlockNum) assert.Equal(t, newOpenAuctionSlots, auctionEvents.NewOpenAuctionSlots[0].NewOpenAuctionSlots) } @@ -115,8 +115,8 @@ func TestAuctionSetClosedAuctionSlots(t *testing.T) { closedAuctionSlots, err := auctionClient.AuctionGetClosedAuctionSlots() require.Nil(t, err) assert.Equal(t, newClosedAuctionSlots, closedAuctionSlots) - header, _ := auctionClient.client.client.HeaderByNumber(context.Background(), nil) - auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(header.Number.Int64()) + currentBlockNum, _ := auctionClient.client.EthCurrentBlock() + auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(currentBlockNum) assert.Equal(t, newClosedAuctionSlots, auctionEvents.NewClosedAuctionSlots[0].NewClosedAuctionSlots) _, err = auctionClient.AuctionSetClosedAuctionSlots(closedAuctionSlots) require.Nil(t, err) @@ -136,8 +136,8 @@ func TestAuctionSetOutbidding(t *testing.T) { outbidding, err := auctionClient.AuctionGetOutbidding() require.Nil(t, err) assert.Equal(t, newOutbidding, outbidding) - header, _ := auctionClient.client.client.HeaderByNumber(context.Background(), nil) - auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(header.Number.Int64()) + currentBlockNum, _ := auctionClient.client.EthCurrentBlock() + auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(currentBlockNum) assert.Equal(t, newOutbidding, auctionEvents.NewOutbidding[0].NewOutbidding) _, err = auctionClient.AuctionSetOutbidding(outbiddingConst) require.Nil(t, err) @@ -157,8 +157,8 @@ func TestAuctionSetAllocationRatio(t *testing.T) { allocationRatio, err := auctionClient.AuctionGetAllocationRatio() require.Nil(t, err) assert.Equal(t, newAllocationRatio, allocationRatio) - header, _ := auctionClient.client.client.HeaderByNumber(context.Background(), nil) - auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(header.Number.Int64()) + currentBlockNum, _ := auctionClient.client.EthCurrentBlock() + auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(currentBlockNum) assert.Equal(t, newAllocationRatio, auctionEvents.NewAllocationRatio[0].NewAllocationRatio) _, err = auctionClient.AuctionSetAllocationRatio(allocationRatioConst) require.Nil(t, err) @@ -184,8 +184,8 @@ func TestAuctionSetDonationAddress(t *testing.T) { donationAddress, err := auctionClient.AuctionGetDonationAddress() require.Nil(t, err) assert.Equal(t, &newDonationAddress, donationAddress) - header, _ := auctionClient.client.client.HeaderByNumber(context.Background(), nil) - auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(header.Number.Int64()) + currentBlockNum, _ := auctionClient.client.EthCurrentBlock() + auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(currentBlockNum) assert.Equal(t, newDonationAddress, auctionEvents.NewDonationAddress[0].NewDonationAddress) _, err = auctionClient.AuctionSetDonationAddress(donationAddressConst) require.Nil(t, err) @@ -199,8 +199,8 @@ func TestAuctionSetBootCoordinator(t *testing.T) { bootCoordinator, err := auctionClient.AuctionGetBootCoordinator() require.Nil(t, err) assert.Equal(t, &newBootCoordinator, bootCoordinator) - header, _ := auctionClient.client.client.HeaderByNumber(context.Background(), nil) - auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(header.Number.Int64()) + currentBlockNum, _ := auctionClient.client.EthCurrentBlock() + auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(currentBlockNum) assert.Equal(t, newBootCoordinator, auctionEvents.NewBootCoordinator[0].NewBootCoordinator) _, err = auctionClient.AuctionSetBootCoordinator(bootCoordinatorAddressConst) require.Nil(t, err) @@ -233,8 +233,8 @@ func TestAuctionChangeDefaultSlotSetBid(t *testing.T) { minBid, err := auctionClient.AuctionGetDefaultSlotSetBid(set) require.Nil(t, err) assert.Equal(t, minBid, newInitialMinBid) - header, _ := auctionClient.client.client.HeaderByNumber(context.Background(), nil) - auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(header.Number.Int64()) + currentBlockNum, _ := auctionClient.client.EthCurrentBlock() + auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(currentBlockNum) assert.Equal(t, slotSet, auctionEvents.NewDefaultSlotSetBid[0].SlotSet) assert.Equal(t, newInitialMinBid, auctionEvents.NewDefaultSlotSetBid[0].NewInitialMinBid) newMinBid := new(big.Int) @@ -264,8 +264,8 @@ func TestAuctionRegisterCoordinator(t *testing.T) { _, err := auctionClient.AuctionRegisterCoordinator(forgerAddress, URL) require.Nil(t, err) - header, _ := auctionClient.client.client.HeaderByNumber(context.Background(), nil) - auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(header.Number.Int64()) + currentBlockNum, _ := auctionClient.client.EthCurrentBlock() + auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(currentBlockNum) assert.Equal(t, forgerAddress, auctionEvents.NewCoordinator[0].ForgerAddress) assert.Equal(t, forgerAddress, auctionEvents.NewCoordinator[0].WithdrawalAddress) assert.Equal(t, URL, auctionEvents.NewCoordinator[0].CoordinatorURL) @@ -284,8 +284,8 @@ func TestAuctionUpdateCoordinatorInfo(t *testing.T) { _, err := auctionClient.AuctionUpdateCoordinatorInfo(forgerAddress, forgerAddress, newURL) require.Nil(t, err) - header, _ := auctionClient.client.client.HeaderByNumber(context.Background(), nil) - auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(header.Number.Int64()) + currentBlockNum, _ := auctionClient.client.EthCurrentBlock() + auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(currentBlockNum) assert.Equal(t, forgerAddress, auctionEvents.CoordinatorUpdated[0].ForgerAddress) assert.Equal(t, forgerAddress, auctionEvents.CoordinatorUpdated[0].WithdrawalAddress) assert.Equal(t, newURL, auctionEvents.CoordinatorUpdated[0].CoordinatorURL) @@ -299,8 +299,8 @@ func TestAuctionBid(t *testing.T) { forgerAddress := governanceAddressConst _, err = auctionClient.AuctionBid(currentSlot+4, bidAmount, forgerAddress) require.Nil(t, err) - header, _ := auctionClient.client.client.HeaderByNumber(context.Background(), nil) - auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(header.Number.Int64()) + currentBlockNum, _ := auctionClient.client.EthCurrentBlock() + auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(currentBlockNum) assert.Equal(t, bidAmount, auctionEvents.NewBid[0].BidAmount) assert.Equal(t, forgerAddress, auctionEvents.NewBid[0].CoordinatorForger) assert.Equal(t, currentSlot+4, auctionEvents.NewBid[0].Slot) @@ -337,8 +337,8 @@ func TestAuctionMultiBid(t *testing.T) { forgerAddress := governanceAddressConst _, err = auctionClient.AuctionMultiBid(currentSlot+4, currentSlot+10, slotSet, maxBid, minBid, budget, forgerAddress) require.Nil(t, err) - header, _ := auctionClient.client.client.HeaderByNumber(context.Background(), nil) - auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(header.Number.Int64()) + currentBlockNum, _ := auctionClient.client.EthCurrentBlock() + auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(currentBlockNum) assert.Equal(t, forgerAddress, auctionEvents.NewBid[0].CoordinatorForger) assert.Equal(t, currentSlot+4, auctionEvents.NewBid[0].Slot) assert.Equal(t, forgerAddress, auctionEvents.NewBid[1].CoordinatorForger) @@ -365,8 +365,24 @@ func TestAuctionClaimHEZ(t *testing.T) { _, err := auctionClient.AuctionClaimHEZ(governanceAddressConst) require.Nil(t, err) - header, _ := auctionClient.client.client.HeaderByNumber(context.Background(), nil) - auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(header.Number.Int64()) + currentBlockNum, _ := auctionClient.client.EthCurrentBlock() + auctionEvents, _, _ := auctionClient.AuctionEventsByBlock(currentBlockNum) assert.Equal(t, amount, auctionEvents.HEZClaimed[0].Amount) assert.Equal(t, governanceAddressConst, auctionEvents.HEZClaimed[0].Owner) } + +func TestAuctionForge(t *testing.T) { + auctionClientHermez, err := NewAuctionClient(ethereumClientHermez, auctionAddressConst, tokenHezAddressConst) + require.Nil(t, err) + slotConst := 4 + blockNum := int64(int(BLOCKSPERSLOT)*slotConst + genesisBlock) + currentBlockNum, _ := auctionClient.client.EthCurrentBlock() + blocksToAdd := blockNum - currentBlockNum + addBlocks(blocksToAdd, ethClientDialURL) + currentBlockNum, _ = auctionClient.client.EthCurrentBlock() + assert.Equal(t, currentBlockNum, blockNum) + _, err = auctionClientHermez.AuctionForge(bootCoordinatorAddressConst) + require.Contains(t, err.Error(), "Can't forge") + _, err = auctionClientHermez.AuctionForge(governanceAddressConst) + require.Nil(t, err) +} diff --git a/eth/helpers.go b/eth/helpers.go new file mode 100644 index 0000000..0d60ceb --- /dev/null +++ b/eth/helpers.go @@ -0,0 +1,63 @@ +package eth + +import ( + "fmt" + "net/http" + "strconv" + "strings" +) + +func addBlock(url string) { + method := "POST" + + payload := strings.NewReader("{\n \"jsonrpc\":\"2.0\",\n \"method\":\"evm_mine\",\n \"params\":[],\n \"id\":1\n}") + + client := &http.Client{} + req, err := http.NewRequest(method, url, payload) + + if err != nil { + fmt.Println(err) + } + req.Header.Add("Content-Type", "application/json") + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + } + defer func() { + if err := res.Body.Close(); err != nil { + fmt.Println("Error when closing:", err) + } + }() +} + +func addBlocks(numBlocks int64, url string) { + for i := int64(0); i < numBlocks; i++ { + addBlock(url) + } +} + +func addTime(seconds float64, url string) { + secondsStr := strconv.FormatFloat(seconds, 'E', -1, 32) + + method := "POST" + payload := strings.NewReader("{\n \"jsonrpc\":\"2.0\",\n \"method\":\"evm_increaseTime\",\n \"params\":[" + secondsStr + "],\n \"id\":1\n}") + + client := &http.Client{} + req, err := http.NewRequest(method, url, payload) + + if err != nil { + fmt.Println(err) + } + req.Header.Add("Content-Type", "application/json") + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + } + defer func() { + if err := res.Body.Close(); err != nil { + fmt.Println("Error when closing:", err) + } + }() +} diff --git a/eth/main_test.go b/eth/main_test.go index e714b73..2fba7eb 100644 --- a/eth/main_test.go +++ b/eth/main_test.go @@ -19,13 +19,15 @@ var tokenHezStr = os.Getenv("TOKEN_ADDRESS") var hermezStr = os.Getenv("HERMEZ_ADDRESS") var governanceAddressStr = os.Getenv("GOV_ADDRESS") var governancePrivateKey = os.Getenv("GOV_PK") -var ehtClientDialURL = os.Getenv("ETHCLIENT_DIAL_URL")*/ -var ehtClientDialURL = "http://localhost:8545" +var ethClientDialURL = os.Getenv("ETHCLIENT_DIAL_URL")*/ +var ethClientDialURL = "http://localhost:8545" var password = "pass" // Smart Contract Addresses var ( - auctionAddressStr = "0x3619DbE27d7c1e7E91aA738697Ae7Bc5FC3eACA5" + // auctionAddressStr = "0x3619DbE27d7c1e7E91aA738697Ae7Bc5FC3eACA5" + // wdelayerAddressStr = "0x1A1FEe7EeD918BD762173e4dc5EfDB8a78C924A8" + auctionAddressStr = "0x8B5B7a6055E54a36fF574bbE40cf2eA68d5554b3" auctionAddressConst = ethCommon.HexToAddress(auctionAddressStr) donationAddressStr = "0x6c365935CA8710200C7595F0a72EB6023A7706Cd" donationAddressConst = ethCommon.HexToAddress(donationAddressStr) @@ -35,7 +37,7 @@ var ( tokenHezAddressConst = ethCommon.HexToAddress(tokenHezAddressStr) hermezRollupAddressStr = "0xc4905364b78a742ccce7B890A89514061E47068D" hermezRollupAddressConst = ethCommon.HexToAddress(hermezRollupAddressStr) - wdelayerAddressStr = "0x1A1FEe7EeD918BD762173e4dc5EfDB8a78C924A8" + wdelayerAddressStr = "0x20Ce94F404343aD2752A2D01b43fa407db9E0D00" wdelayerAddressConst = ethCommon.HexToAddress(wdelayerAddressStr) ) @@ -60,6 +62,10 @@ var ( auxAddressSK = "28d1bfbbafe9d1d4f5a11c3c16ab6bf9084de48d99fbac4058bdfa3c80b29089" auxAddressStr = "0x3d91185a02774C70287F6c74Dd26d13DFB58ff16" auxAddressConst = ethCommon.HexToAddress(auxAddressStr) + + hermezRollupTestSK = "28d1bfbbafe9d1d4f5a11c3c16ab6bf9084de48d99fbac4058bdfa3c80b29088" + hermezRollupTestAddressStr = "0xEa960515F8b4C237730F028cBAcF0a28E7F45dE0" + hermezRollupAddressTestConst = ethCommon.HexToAddress(hermezRollupTestAddressStr) ) var ( @@ -68,12 +74,14 @@ var ( accountWhite *accounts.Account accountGovDAO *accounts.Account accountAux *accounts.Account + accountHermez *accounts.Account ks *keystore.KeyStore ethClient *ethclient.Client ethereumClientWhite *EthereumClient ethereumClientKep *EthereumClient ethereumClientGovDAO *EthereumClient ethereumClientAux *EthereumClient + ethereumClientHermez *EthereumClient ) func addKey(ks *keystore.KeyStore, skHex string) *accounts.Account { @@ -108,8 +116,9 @@ func TestMain(m *testing.M) { accountWhite = addKey(ks, whiteHackGroupAddressSK) accountGovDAO = addKey(ks, hermezGovernanceDAOAddressSK) accountAux = addKey(ks, auxAddressSK) + accountHermez = addKey(ks, hermezRollupTestSK) - ethClient, err = ethclient.Dial(ehtClientDialURL) + ethClient, err = ethclient.Dial(ethClientDialURL) if err != nil { panic(err) } @@ -117,14 +126,15 @@ func TestMain(m *testing.M) { // Controllable Governance Address ethereumClientGov := NewEthereumClient(ethClient, accountGov, ks, nil) - auctionClient = NewAuctionClient(ethereumClientGov, auctionAddressConst, tokenHezAddressConst) + auctionClient, _ = NewAuctionClient(ethereumClientGov, auctionAddressConst, tokenHezAddressConst) rollupClient = NewRollupClient(ethereumClientGov, hermezRollupAddressConst) - wdelayerClient = NewWDelayerClient(ethereumClientGov, wdelayerAddressConst) + wdelayerClient, _ = NewWDelayerClient(ethereumClientGov, wdelayerAddressConst) ethereumClientKep = NewEthereumClient(ethClient, accountKep, ks, nil) ethereumClientWhite = NewEthereumClient(ethClient, accountWhite, ks, nil) ethereumClientGovDAO = NewEthereumClient(ethClient, accountGovDAO, ks, nil) ethereumClientAux = NewEthereumClient(ethClient, accountAux, ks, nil) + ethereumClientHermez = NewEthereumClient(ethClient, accountHermez, ks, nil) exitVal = m.Run() } diff --git a/eth/wdelayer.go b/eth/wdelayer.go index ce7d30d..43584ea 100644 --- a/eth/wdelayer.go +++ b/eth/wdelayer.go @@ -1,12 +1,17 @@ package eth import ( + "context" "fmt" "math/big" + "strings" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" ethCommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" WithdrawalDelayer "github.com/hermeznetwork/hermez-node/eth/contracts/withdrawdelayer" ) @@ -128,18 +133,24 @@ type WDelayerInterface interface { // WDelayerClient is the implementation of the interface to the WithdrawDelayer Smart Contract in ethereum. type WDelayerClient struct { - client *EthereumClient - address ethCommon.Address - gasLimit uint64 + client *EthereumClient + address ethCommon.Address + gasLimit uint64 + contractAbi abi.ABI } // NewWDelayerClient creates a new WDelayerClient -func NewWDelayerClient(client *EthereumClient, address ethCommon.Address) *WDelayerClient { - return &WDelayerClient{ - client: client, - address: address, - gasLimit: 1000000, //nolint:gomnd +func NewWDelayerClient(client *EthereumClient, address ethCommon.Address) (*WDelayerClient, error) { + contractAbi, err := abi.JSON(strings.NewReader(string(WithdrawalDelayer.WithdrawalDelayerABI))) + if err != nil { + return nil, err } + return &WDelayerClient{ + client: client, + address: address, + gasLimit: 1000000, //nolint:gomnd + contractAbi: contractAbi, + }, nil } // WDelayerGetHermezGovernanceDAOAddress is the interface to call the smart contract function @@ -407,3 +418,108 @@ func (c *WDelayerClient) WDelayerEscapeHatchWithdrawal(to, token ethCommon.Addre } return tx, nil } + +var ( + logDeposit = crypto.Keccak256Hash([]byte("Deposit(address,address,uint192,uint64)")) + logWithdraw = crypto.Keccak256Hash([]byte("Withdraw(address,address,uint192)")) + logEmergencyModeEnabled = crypto.Keccak256Hash([]byte("EmergencyModeEnabled()")) + logNewWithdrawalDelay = crypto.Keccak256Hash([]byte("NewWithdrawalDelay(uint64)")) + logEscapeHatchWithdrawal = crypto.Keccak256Hash([]byte("EscapeHatchWithdrawal(address,address,address)")) + logNewHermezKeeperAddress = crypto.Keccak256Hash([]byte("NewHermezKeeperAddress(address)")) + logNewWhiteHackGroupAddress = crypto.Keccak256Hash([]byte("NewWhiteHackGroupAddress(address)")) + logNewHermezGovernanceDAOAddress = crypto.Keccak256Hash([]byte("NewHermezGovernanceDAOAddress(address)")) +) + +// WDelayerEventsByBlock returns the events in a block that happened in the WDelayer Smart Contract +func (c *WDelayerClient) WDelayerEventsByBlock(blockNum int64) (*WDelayerEvents, *ethCommon.Hash, error) { + var wdelayerEvents WDelayerEvents + var blockHash ethCommon.Hash + + query := ethereum.FilterQuery{ + FromBlock: big.NewInt(blockNum), + ToBlock: big.NewInt(blockNum), + Addresses: []ethCommon.Address{ + c.address, + }, + BlockHash: nil, + Topics: [][]ethCommon.Hash{}, + } + + logs, err := c.client.client.FilterLogs(context.Background(), query) + if err != nil { + fmt.Println(err) + } + if len(logs) > 0 { + blockHash = logs[0].BlockHash + } + for _, vLog := range logs { + if vLog.BlockHash != blockHash { + return nil, nil, err + } + switch vLog.Topics[0] { + case logDeposit: + var deposit WDelayerEventDeposit + err := c.contractAbi.Unpack(&deposit, "Deposit", vLog.Data) + if err != nil { + return nil, nil, err + } + deposit.Owner = ethCommon.BytesToAddress(vLog.Topics[1].Bytes()) + deposit.Token = ethCommon.BytesToAddress(vLog.Topics[2].Bytes()) + wdelayerEvents.Deposit = append(wdelayerEvents.Deposit, deposit) + + case logWithdraw: + var withdraw WDelayerEventWithdraw + err := c.contractAbi.Unpack(&withdraw, "Withdraw", vLog.Data) + if err != nil { + return nil, nil, err + } + withdraw.Token = ethCommon.BytesToAddress(vLog.Topics[1].Bytes()) + withdraw.Owner = ethCommon.BytesToAddress(vLog.Topics[2].Bytes()) + wdelayerEvents.Withdraw = append(wdelayerEvents.Withdraw, withdraw) + + case logEmergencyModeEnabled: + var emergencyModeEnabled WDelayerEventEmergencyModeEnabled + wdelayerEvents.EmergencyModeEnabled = append(wdelayerEvents.EmergencyModeEnabled, emergencyModeEnabled) + + case logNewWithdrawalDelay: + var withdrawalDelay WDelayerEventNewWithdrawalDelay + err := c.contractAbi.Unpack(&withdrawalDelay, "NewWithdrawalDelay", vLog.Data) + if err != nil { + return nil, nil, err + } + wdelayerEvents.NewWithdrawalDelay = append(wdelayerEvents.NewWithdrawalDelay, withdrawalDelay) + + case logEscapeHatchWithdrawal: + var escapeHatchWithdrawal WDelayerEventEscapeHatchWithdrawal + escapeHatchWithdrawal.Who = ethCommon.BytesToAddress(vLog.Topics[1].Bytes()) + escapeHatchWithdrawal.To = ethCommon.BytesToAddress(vLog.Topics[2].Bytes()) + escapeHatchWithdrawal.Token = ethCommon.BytesToAddress(vLog.Topics[3].Bytes()) + wdelayerEvents.EscapeHatchWithdrawal = append(wdelayerEvents.EscapeHatchWithdrawal, escapeHatchWithdrawal) + + case logNewHermezKeeperAddress: + var keeperAddress WDelayerEventNewHermezKeeperAddress + err := c.contractAbi.Unpack(&keeperAddress, "NewHermezKeeperAddress", vLog.Data) + if err != nil { + return nil, nil, err + } + wdelayerEvents.NewHermezKeeperAddress = append(wdelayerEvents.NewHermezKeeperAddress, keeperAddress) + + case logNewWhiteHackGroupAddress: + var whiteHackGroupAddress WDelayerEventNewWhiteHackGroupAddress + err := c.contractAbi.Unpack(&whiteHackGroupAddress, "NewWhiteHackGroupAddress", vLog.Data) + if err != nil { + return nil, nil, err + } + wdelayerEvents.NewWhiteHackGroupAddress = append(wdelayerEvents.NewWhiteHackGroupAddress, whiteHackGroupAddress) + + case logNewHermezGovernanceDAOAddress: + var governanceDAOAddress WDelayerEventNewHermezGovernanceDAOAddress + err := c.contractAbi.Unpack(&governanceDAOAddress, "NewHermezGovernanceDAOAddress", vLog.Data) + if err != nil { + return nil, nil, err + } + wdelayerEvents.NewHermezGovernanceDAOAddress = append(wdelayerEvents.NewHermezGovernanceDAOAddress, governanceDAOAddress) + } + } + return &wdelayerEvents, &blockHash, nil +} diff --git a/eth/wdelayer_test.go b/eth/wdelayer_test.go index e081a9a..4c2a5cb 100644 --- a/eth/wdelayer_test.go +++ b/eth/wdelayer_test.go @@ -3,6 +3,7 @@ package eth import ( "math/big" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -14,6 +15,7 @@ var wdelayerClient *WDelayerClient var initWithdrawalDelay = big.NewInt(60) var newWithdrawalDelay = big.NewInt(79) +var maxEmergencyModeTime = time.Hour * 24 * 7 * 26 func TestWDelayerGetHermezGovernanceDAOAddress(t *testing.T) { governanceAddress, err := wdelayerClient.WDelayerGetHermezGovernanceDAOAddress() @@ -22,13 +24,18 @@ func TestWDelayerGetHermezGovernanceDAOAddress(t *testing.T) { } func TestWDelayerSetHermezGovernanceDAOAddress(t *testing.T) { - wdelayerClientGov := NewWDelayerClient(ethereumClientGovDAO, wdelayerAddressConst) - _, err := wdelayerClientGov.WDelayerSetHermezGovernanceDAOAddress(auxAddressConst) + wdelayerClientGov, err := NewWDelayerClient(ethereumClientGovDAO, wdelayerAddressConst) + require.Nil(t, err) + _, err = wdelayerClientGov.WDelayerSetHermezGovernanceDAOAddress(auxAddressConst) require.Nil(t, err) auxAddress, err := wdelayerClient.WDelayerGetHermezGovernanceDAOAddress() require.Nil(t, err) assert.Equal(t, &auxAddressConst, auxAddress) - wdelayerClientAux := NewWDelayerClient(ethereumClientAux, wdelayerAddressConst) + currentBlockNum, _ := wdelayerClient.client.EthCurrentBlock() + wdelayerEvents, _, _ := wdelayerClient.WDelayerEventsByBlock(currentBlockNum) + assert.Equal(t, auxAddressConst, wdelayerEvents.NewHermezGovernanceDAOAddress[0].NewHermezGovernanceDAOAddress) + wdelayerClientAux, err := NewWDelayerClient(ethereumClientAux, wdelayerAddressConst) + require.Nil(t, err) _, err = wdelayerClientAux.WDelayerSetHermezGovernanceDAOAddress(hermezGovernanceDAOAddressConst) require.Nil(t, err) } @@ -40,13 +47,18 @@ func TestWDelayerGetHermezKeeperAddress(t *testing.T) { } func TestWDelayerSetHermezKeeperAddress(t *testing.T) { - wdelayerClientKep := NewWDelayerClient(ethereumClientKep, wdelayerAddressConst) - _, err := wdelayerClientKep.WDelayerSetHermezKeeperAddress(auxAddressConst) + wdelayerClientKep, err := NewWDelayerClient(ethereumClientKep, wdelayerAddressConst) + require.Nil(t, err) + _, err = wdelayerClientKep.WDelayerSetHermezKeeperAddress(auxAddressConst) require.Nil(t, err) auxAddress, err := wdelayerClient.WDelayerGetHermezKeeperAddress() require.Nil(t, err) assert.Equal(t, &auxAddressConst, auxAddress) - wdelayerClientAux := NewWDelayerClient(ethereumClientAux, wdelayerAddressConst) + currentBlockNum, _ := wdelayerClient.client.EthCurrentBlock() + wdelayerEvents, _, _ := wdelayerClient.WDelayerEventsByBlock(currentBlockNum) + assert.Equal(t, auxAddressConst, wdelayerEvents.NewHermezKeeperAddress[0].NewHermezKeeperAddress) + wdelayerClientAux, err := NewWDelayerClient(ethereumClientAux, wdelayerAddressConst) + require.Nil(t, err) _, err = wdelayerClientAux.WDelayerSetHermezKeeperAddress(hermezKeeperAddressConst) require.Nil(t, err) } @@ -58,13 +70,18 @@ func TestWDelayerGetWhiteHackGroupAddress(t *testing.T) { } func TestWDelayerSetWhiteHackGroupAddress(t *testing.T) { - wdelayerClientWhite := NewWDelayerClient(ethereumClientWhite, wdelayerAddressConst) - _, err := wdelayerClientWhite.WDelayerSetWhiteHackGroupAddress(auxAddressConst) + wdelayerClientWhite, err := NewWDelayerClient(ethereumClientWhite, wdelayerAddressConst) + require.Nil(t, err) + _, err = wdelayerClientWhite.WDelayerSetWhiteHackGroupAddress(auxAddressConst) require.Nil(t, err) auxAddress, err := wdelayerClient.WDelayerGetWhiteHackGroupAddress() require.Nil(t, err) assert.Equal(t, &auxAddressConst, auxAddress) - wdelayerClientAux := NewWDelayerClient(ethereumClientAux, wdelayerAddressConst) + currentBlockNum, _ := wdelayerClient.client.EthCurrentBlock() + wdelayerEvents, _, _ := wdelayerClient.WDelayerEventsByBlock(currentBlockNum) + assert.Equal(t, auxAddressConst, wdelayerEvents.NewWhiteHackGroupAddress[0].NewWhiteHackGroupAddress) + wdelayerClientAux, err := NewWDelayerClient(ethereumClientAux, wdelayerAddressConst) + require.Nil(t, err) _, err = wdelayerClientAux.WDelayerSetWhiteHackGroupAddress(whiteHackGroupAddressConst) require.Nil(t, err) } @@ -81,22 +98,68 @@ func TestWDelayerGetWithdrawalDelay(t *testing.T) { assert.Equal(t, initWithdrawalDelay, withdrawalDelay) } -func TestWDelayerEnableEmergencyMode(t *testing.T) { - wdelayerClientKep := NewWDelayerClient(ethereumClientKep, wdelayerAddressConst) - _, err := wdelayerClientKep.WDelayerEnableEmergencyMode() +func TestWDelayerChangeWithdrawalDelay(t *testing.T) { + wdelayerClientKep, err := NewWDelayerClient(ethereumClientKep, wdelayerAddressConst) require.Nil(t, err) - emergencyMode, err := wdelayerClient.WDelayerIsEmergencyMode() + _, err = wdelayerClientKep.WDelayerChangeWithdrawalDelay(newWithdrawalDelay.Uint64()) require.Nil(t, err) - assert.Equal(t, true, emergencyMode) + withdrawalDelay, err := wdelayerClient.WDelayerGetWithdrawalDelay() + require.Nil(t, err) + assert.Equal(t, newWithdrawalDelay, withdrawalDelay) + currentBlockNum, _ := wdelayerClient.client.EthCurrentBlock() + wdelayerEvents, _, _ := wdelayerClient.WDelayerEventsByBlock(currentBlockNum) + assert.Equal(t, newWithdrawalDelay.Uint64(), wdelayerEvents.NewWithdrawalDelay[0].WithdrawalDelay) } -func TestWDelayerChangeWithdrawalDelay(t *testing.T) { - wdelayerClientKep := NewWDelayerClient(ethereumClientKep, wdelayerAddressConst) - _, err := wdelayerClientKep.WDelayerChangeWithdrawalDelay(newWithdrawalDelay.Uint64()) +func TestWDelayerDeposit(t *testing.T) { + amount := new(big.Int) + amount.SetString("1100000000000000000", 10) + wdelayerClientHermez, err := NewWDelayerClient(ethereumClientHermez, wdelayerAddressConst) require.Nil(t, err) - withdrawalDelay, err := wdelayerClient.WDelayerGetWithdrawalDelay() + _, err = wdelayerClientHermez.WDelayerDeposit(auxAddressConst, tokenHezAddressConst, amount) require.Nil(t, err) - assert.Equal(t, newWithdrawalDelay, withdrawalDelay) + currentBlockNum, _ := wdelayerClient.client.EthCurrentBlock() + wdelayerEvents, _, _ := wdelayerClient.WDelayerEventsByBlock(currentBlockNum) + assert.Equal(t, amount, wdelayerEvents.Deposit[0].Amount) + assert.Equal(t, auxAddressConst, wdelayerEvents.Deposit[0].Owner) + assert.Equal(t, tokenHezAddressConst, wdelayerEvents.Deposit[0].Token) +} + +func TestWDelayerDepositInfo(t *testing.T) { + amount := new(big.Int) + amount.SetString("1100000000000000000", 10) + state, err := wdelayerClient.WDelayerDepositInfo(auxAddressConst, tokenHezAddressConst) + require.Nil(t, err) + assert.Equal(t, state.Amount, amount) +} + +func TestWDelayerWithdrawal(t *testing.T) { + amount := new(big.Int) + amount.SetString("1100000000000000000", 10) + _, err := wdelayerClient.WDelayerWithdrawal(auxAddressConst, tokenHezAddressConst) + require.Contains(t, err.Error(), "Withdrawal not allowed yet") + addBlocks(newWithdrawalDelay.Int64(), ethClientDialURL) + _, err = wdelayerClient.WDelayerWithdrawal(auxAddressConst, tokenHezAddressConst) + require.Nil(t, err) + currentBlockNum, _ := wdelayerClient.client.EthCurrentBlock() + wdelayerEvents, _, _ := wdelayerClient.WDelayerEventsByBlock(currentBlockNum) + assert.Equal(t, amount, wdelayerEvents.Withdraw[0].Amount) + assert.Equal(t, auxAddressConst, wdelayerEvents.Withdraw[0].Owner) + assert.Equal(t, tokenHezAddressConst, wdelayerEvents.Withdraw[0].Token) +} + +func TestWDelayerEnableEmergencyMode(t *testing.T) { + wdelayerClientKep, err := NewWDelayerClient(ethereumClientKep, wdelayerAddressConst) + require.Nil(t, err) + _, err = wdelayerClientKep.WDelayerEnableEmergencyMode() + require.Nil(t, err) + emergencyMode, err := wdelayerClient.WDelayerIsEmergencyMode() + require.Nil(t, err) + assert.Equal(t, true, emergencyMode) + currentBlockNum, _ := wdelayerClient.client.EthCurrentBlock() + wdelayerEvents, _, _ := wdelayerClient.WDelayerEventsByBlock(currentBlockNum) + auxEvent := new(WDelayerEventEmergencyModeEnabled) + assert.Equal(t, auxEvent, &wdelayerEvents.EmergencyModeEnabled[0]) } func TestWDelayerGetEmergencyModeStartingTime(t *testing.T) { @@ -109,26 +172,18 @@ func TestWDelayerGetEmergencyModeStartingTime(t *testing.T) { assert.True(t, emergencyModeStartingTime.Cmp(big.NewInt(0)) == 1) } -/* func TestWDelayerDeposit(t *testing.T) { - if wdelayerClient != nil { - - } -} - -func TestWDelayerDepositInfo(t *testing.T) { - if wdelayerClient != nil { - - } -} - -func TestWDelayerWithdrawal(t *testing.T) { - if wdelayerClient != nil { - - } -} - func TestWDelayerEscapeHatchWithdrawal(t *testing.T) { - if wdelayerClient != nil { - - } -} */ + wdelayerClientWhite, err := NewWDelayerClient(ethereumClientWhite, wdelayerAddressConst) + require.Nil(t, err) + _, err = wdelayerClientWhite.WDelayerEscapeHatchWithdrawal(governanceAddressConst, tokenHezAddressConst) + require.Contains(t, err.Error(), "NO MAX_EMERGENCY_MODE_TIME") + seconds := maxEmergencyModeTime.Seconds() + addTime(seconds, ethClientDialURL) + _, err = wdelayerClientWhite.WDelayerEscapeHatchWithdrawal(governanceAddressConst, tokenHezAddressConst) + require.Nil(t, err) + currentBlockNum, _ := wdelayerClient.client.EthCurrentBlock() + wdelayerEvents, _, _ := wdelayerClient.WDelayerEventsByBlock(currentBlockNum) + assert.Equal(t, tokenHezAddressConst, wdelayerEvents.EscapeHatchWithdrawal[0].Token) + assert.Equal(t, governanceAddressConst, wdelayerEvents.EscapeHatchWithdrawal[0].To) + assert.Equal(t, whiteHackGroupAddressConst, wdelayerEvents.EscapeHatchWithdrawal[0].Who) +} From ca3ae28f4625f9b788079b4bd9d6456584174aa2 Mon Sep 17 00:00:00 2001 From: Eduard S Date: Wed, 30 Sep 2020 11:58:31 +0200 Subject: [PATCH 2/2] Add missing error handling --- eth/auction.go | 8 +++++--- eth/ethereum.go | 3 +++ eth/main_test.go | 10 ++++++++-- eth/wdelayer.go | 8 +++++--- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/eth/auction.go b/eth/auction.go index 27d07ce..d2cccb8 100644 --- a/eth/auction.go +++ b/eth/auction.go @@ -958,7 +958,9 @@ var ( logHEZClaimed = crypto.Keccak256Hash([]byte("HEZClaimed(address,uint128)")) ) -// AuctionEventsByBlock returns the events in a block that happened in the Auction Smart Contract +// AuctionEventsByBlock returns the events in a block that happened in the +// Auction Smart Contract and the blockHash where the eents happened. If there +// are no events in that block, blockHash is nil. func (c *AuctionClient) AuctionEventsByBlock(blockNum int64) (*AuctionEvents, *ethCommon.Hash, error) { var auctionEvents AuctionEvents var blockHash ethCommon.Hash @@ -974,14 +976,14 @@ func (c *AuctionClient) AuctionEventsByBlock(blockNum int64) (*AuctionEvents, *e logs, err := c.client.client.FilterLogs(context.TODO(), query) if err != nil { - fmt.Println(err) + return nil, nil, err } if len(logs) > 0 { blockHash = logs[0].BlockHash } for _, vLog := range logs { if vLog.BlockHash != blockHash { - return nil, nil, err + return nil, nil, ErrBlockHashMismatchEvent } switch vLog.Topics[0] { case logNewBid: diff --git a/eth/ethereum.go b/eth/ethereum.go index 711e4c9..89617f8 100644 --- a/eth/ethereum.go +++ b/eth/ethereum.go @@ -30,6 +30,9 @@ var ( ErrReceiptStatusFailed = fmt.Errorf("receipt status is failed") // ErrReceiptNotReceived is used when unable to retrieve a transaction ErrReceiptNotReceived = fmt.Errorf("receipt not available") + // ErrBlockHashMismatchEvent is used when there's a block hash mismatch + // beetween different events of the same block + ErrBlockHashMismatchEvent = fmt.Errorf("block hash mismatch in event log") ) const ( diff --git a/eth/main_test.go b/eth/main_test.go index 2fba7eb..63589b7 100644 --- a/eth/main_test.go +++ b/eth/main_test.go @@ -126,9 +126,15 @@ func TestMain(m *testing.M) { // Controllable Governance Address ethereumClientGov := NewEthereumClient(ethClient, accountGov, ks, nil) - auctionClient, _ = NewAuctionClient(ethereumClientGov, auctionAddressConst, tokenHezAddressConst) + auctionClient, err = NewAuctionClient(ethereumClientGov, auctionAddressConst, tokenHezAddressConst) + if err != nil { + panic(err) + } rollupClient = NewRollupClient(ethereumClientGov, hermezRollupAddressConst) - wdelayerClient, _ = NewWDelayerClient(ethereumClientGov, wdelayerAddressConst) + wdelayerClient, err = NewWDelayerClient(ethereumClientGov, wdelayerAddressConst) + if err != nil { + panic(err) + } ethereumClientKep = NewEthereumClient(ethClient, accountKep, ks, nil) ethereumClientWhite = NewEthereumClient(ethClient, accountWhite, ks, nil) diff --git a/eth/wdelayer.go b/eth/wdelayer.go index 43584ea..b89bb68 100644 --- a/eth/wdelayer.go +++ b/eth/wdelayer.go @@ -430,7 +430,9 @@ var ( logNewHermezGovernanceDAOAddress = crypto.Keccak256Hash([]byte("NewHermezGovernanceDAOAddress(address)")) ) -// WDelayerEventsByBlock returns the events in a block that happened in the WDelayer Smart Contract +// WDelayerEventsByBlock returns the events in a block that happened in the +// WDelayer Smart Contract and the blockHash where the eents happened. If +// there are no events in that block, blockHash is nil. func (c *WDelayerClient) WDelayerEventsByBlock(blockNum int64) (*WDelayerEvents, *ethCommon.Hash, error) { var wdelayerEvents WDelayerEvents var blockHash ethCommon.Hash @@ -447,14 +449,14 @@ func (c *WDelayerClient) WDelayerEventsByBlock(blockNum int64) (*WDelayerEvents, logs, err := c.client.client.FilterLogs(context.Background(), query) if err != nil { - fmt.Println(err) + return nil, nil, err } if len(logs) > 0 { blockHash = logs[0].BlockHash } for _, vLog := range logs { if vLog.BlockHash != blockHash { - return nil, nil, err + return nil, nil, ErrBlockHashMismatchEvent } switch vLog.Topics[0] { case logDeposit: