You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

935 lines
36 KiB

4 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
  1. package eth
  2. import (
  3. "context"
  4. "fmt"
  5. "math/big"
  6. "strings"
  7. "github.com/ethereum/go-ethereum"
  8. "github.com/ethereum/go-ethereum/accounts/abi"
  9. "github.com/ethereum/go-ethereum/accounts/abi/bind"
  10. ethCommon "github.com/ethereum/go-ethereum/common"
  11. "github.com/ethereum/go-ethereum/core/types"
  12. "github.com/ethereum/go-ethereum/crypto"
  13. "github.com/ethereum/go-ethereum/ethclient"
  14. "github.com/hermeznetwork/hermez-node/common"
  15. HermezAuctionProtocol "github.com/hermeznetwork/hermez-node/eth/contracts/auction"
  16. HEZ "github.com/hermeznetwork/hermez-node/eth/contracts/tokenHEZ"
  17. "github.com/hermeznetwork/hermez-node/log"
  18. "github.com/hermeznetwork/tracerr"
  19. )
  20. // SlotState is the state of a slot
  21. type SlotState struct {
  22. Bidder ethCommon.Address
  23. ForgerCommitment bool
  24. Fulfilled bool
  25. BidAmount *big.Int
  26. ClosedMinBid *big.Int
  27. }
  28. // NewSlotState returns an empty SlotState
  29. func NewSlotState() *SlotState {
  30. return &SlotState{
  31. Bidder: ethCommon.Address{},
  32. Fulfilled: false,
  33. ForgerCommitment: false,
  34. BidAmount: big.NewInt(0),
  35. ClosedMinBid: big.NewInt(0),
  36. }
  37. }
  38. // Coordinator is the details of the Coordinator identified by the forger address
  39. type Coordinator struct {
  40. Forger ethCommon.Address
  41. URL string
  42. }
  43. // AuctionState represents the state of the Rollup in the Smart Contract
  44. type AuctionState struct {
  45. // Mapping to control slot state
  46. Slots map[int64]*SlotState
  47. // Mapping to control balances pending to claim
  48. PendingBalances map[ethCommon.Address]*big.Int
  49. // Mapping to register all the coordinators. The address used for the mapping is the forger address
  50. Coordinators map[ethCommon.Address]*Coordinator
  51. }
  52. // AuctionEventInitialize is the InitializeHermezAuctionProtocolEvent event of
  53. // the Smart Contract
  54. type AuctionEventInitialize struct {
  55. DonationAddress ethCommon.Address
  56. BootCoordinatorAddress ethCommon.Address
  57. BootCoordinatorURL string
  58. Outbidding uint16
  59. SlotDeadline uint8
  60. ClosedAuctionSlots uint16
  61. OpenAuctionSlots uint16
  62. AllocationRatio [3]uint16
  63. }
  64. // AuctionVariables returns the AuctionVariables from the initialize event
  65. func (ei *AuctionEventInitialize) AuctionVariables(InitialMinimalBidding *big.Int) *common.AuctionVariables {
  66. return &common.AuctionVariables{
  67. EthBlockNum: 0,
  68. DonationAddress: ei.DonationAddress,
  69. BootCoordinator: ei.BootCoordinatorAddress,
  70. BootCoordinatorURL: ei.BootCoordinatorURL,
  71. DefaultSlotSetBid: [6]*big.Int{
  72. InitialMinimalBidding, InitialMinimalBidding, InitialMinimalBidding,
  73. InitialMinimalBidding, InitialMinimalBidding, InitialMinimalBidding,
  74. },
  75. DefaultSlotSetBidSlotNum: 0,
  76. ClosedAuctionSlots: ei.ClosedAuctionSlots,
  77. OpenAuctionSlots: ei.OpenAuctionSlots,
  78. AllocationRatio: ei.AllocationRatio,
  79. Outbidding: ei.Outbidding,
  80. SlotDeadline: ei.SlotDeadline,
  81. }
  82. }
  83. // AuctionEventNewBid is an event of the Auction Smart Contract
  84. type AuctionEventNewBid struct {
  85. Slot int64
  86. BidAmount *big.Int
  87. Bidder ethCommon.Address
  88. }
  89. // AuctionEventNewSlotDeadline is an event of the Auction Smart Contract
  90. type AuctionEventNewSlotDeadline struct {
  91. NewSlotDeadline uint8
  92. }
  93. // AuctionEventNewClosedAuctionSlots is an event of the Auction Smart Contract
  94. type AuctionEventNewClosedAuctionSlots struct {
  95. NewClosedAuctionSlots uint16
  96. }
  97. // AuctionEventNewOutbidding is an event of the Auction Smart Contract
  98. type AuctionEventNewOutbidding struct {
  99. NewOutbidding uint16
  100. }
  101. // AuctionEventNewDonationAddress is an event of the Auction Smart Contract
  102. type AuctionEventNewDonationAddress struct {
  103. NewDonationAddress ethCommon.Address
  104. }
  105. // AuctionEventNewBootCoordinator is an event of the Auction Smart Contract
  106. type AuctionEventNewBootCoordinator struct {
  107. NewBootCoordinator ethCommon.Address
  108. NewBootCoordinatorURL string
  109. }
  110. // AuctionEventNewOpenAuctionSlots is an event of the Auction Smart Contract
  111. type AuctionEventNewOpenAuctionSlots struct {
  112. NewOpenAuctionSlots uint16
  113. }
  114. // AuctionEventNewAllocationRatio is an event of the Auction Smart Contract
  115. type AuctionEventNewAllocationRatio struct {
  116. NewAllocationRatio [3]uint16
  117. }
  118. // AuctionEventSetCoordinator is an event of the Auction Smart Contract
  119. type AuctionEventSetCoordinator struct {
  120. BidderAddress ethCommon.Address
  121. ForgerAddress ethCommon.Address
  122. CoordinatorURL string
  123. }
  124. // AuctionEventNewForgeAllocated is an event of the Auction Smart Contract
  125. type AuctionEventNewForgeAllocated struct {
  126. Bidder ethCommon.Address
  127. Forger ethCommon.Address
  128. SlotToForge int64
  129. BurnAmount *big.Int
  130. DonationAmount *big.Int
  131. GovernanceAmount *big.Int
  132. }
  133. // AuctionEventNewDefaultSlotSetBid is an event of the Auction Smart Contract
  134. type AuctionEventNewDefaultSlotSetBid struct {
  135. SlotSet int64
  136. NewInitialMinBid *big.Int
  137. }
  138. // AuctionEventNewForge is an event of the Auction Smart Contract
  139. type AuctionEventNewForge struct {
  140. Forger ethCommon.Address
  141. SlotToForge int64
  142. }
  143. // AuctionEventHEZClaimed is an event of the Auction Smart Contract
  144. type AuctionEventHEZClaimed struct {
  145. Owner ethCommon.Address
  146. Amount *big.Int
  147. }
  148. // AuctionEvents is the list of events in a block of the Auction Smart Contract
  149. type AuctionEvents struct {
  150. NewBid []AuctionEventNewBid
  151. NewSlotDeadline []AuctionEventNewSlotDeadline
  152. NewClosedAuctionSlots []AuctionEventNewClosedAuctionSlots
  153. NewOutbidding []AuctionEventNewOutbidding
  154. NewDonationAddress []AuctionEventNewDonationAddress
  155. NewBootCoordinator []AuctionEventNewBootCoordinator
  156. NewOpenAuctionSlots []AuctionEventNewOpenAuctionSlots
  157. NewAllocationRatio []AuctionEventNewAllocationRatio
  158. SetCoordinator []AuctionEventSetCoordinator
  159. NewForgeAllocated []AuctionEventNewForgeAllocated
  160. NewDefaultSlotSetBid []AuctionEventNewDefaultSlotSetBid
  161. NewForge []AuctionEventNewForge
  162. HEZClaimed []AuctionEventHEZClaimed
  163. }
  164. // NewAuctionEvents creates an empty AuctionEvents with the slices initialized.
  165. func NewAuctionEvents() AuctionEvents {
  166. return AuctionEvents{
  167. NewBid: make([]AuctionEventNewBid, 0),
  168. NewSlotDeadline: make([]AuctionEventNewSlotDeadline, 0),
  169. NewClosedAuctionSlots: make([]AuctionEventNewClosedAuctionSlots, 0),
  170. NewOutbidding: make([]AuctionEventNewOutbidding, 0),
  171. NewDonationAddress: make([]AuctionEventNewDonationAddress, 0),
  172. NewBootCoordinator: make([]AuctionEventNewBootCoordinator, 0),
  173. NewOpenAuctionSlots: make([]AuctionEventNewOpenAuctionSlots, 0),
  174. NewAllocationRatio: make([]AuctionEventNewAllocationRatio, 0),
  175. SetCoordinator: make([]AuctionEventSetCoordinator, 0),
  176. NewForgeAllocated: make([]AuctionEventNewForgeAllocated, 0),
  177. NewDefaultSlotSetBid: make([]AuctionEventNewDefaultSlotSetBid, 0),
  178. NewForge: make([]AuctionEventNewForge, 0),
  179. HEZClaimed: make([]AuctionEventHEZClaimed, 0),
  180. }
  181. }
  182. // AuctionInterface is the inteface to to Auction Smart Contract
  183. type AuctionInterface interface {
  184. //
  185. // Smart Contract Methods
  186. //
  187. // Getter/Setter, where Setter is onlyOwner
  188. AuctionSetSlotDeadline(newDeadline uint8) (*types.Transaction, error)
  189. AuctionGetSlotDeadline() (uint8, error)
  190. AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (*types.Transaction, error)
  191. AuctionGetOpenAuctionSlots() (uint16, error)
  192. AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (*types.Transaction, error)
  193. AuctionGetClosedAuctionSlots() (uint16, error)
  194. AuctionSetOutbidding(newOutbidding uint16) (*types.Transaction, error)
  195. AuctionGetOutbidding() (uint16, error)
  196. AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (*types.Transaction, error)
  197. AuctionGetAllocationRatio() ([3]uint16, error)
  198. AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (*types.Transaction, error)
  199. AuctionGetDonationAddress() (*ethCommon.Address, error)
  200. AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address, newBootCoordinatorURL string) (*types.Transaction, error)
  201. AuctionGetBootCoordinator() (*ethCommon.Address, error)
  202. AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (*types.Transaction, error)
  203. // Coordinator Management
  204. AuctionSetCoordinator(forger ethCommon.Address, coordinatorURL string) (*types.Transaction, error)
  205. // Slot Info
  206. AuctionGetSlotNumber(blockNum int64) (int64, error)
  207. AuctionGetCurrentSlotNumber() (int64, error)
  208. AuctionGetMinBidBySlot(slot int64) (*big.Int, error)
  209. AuctionGetDefaultSlotSetBid(slotSet uint8) (*big.Int, error)
  210. AuctionGetSlotSet(slot int64) (*big.Int, error)
  211. // Bidding
  212. AuctionBid(amount *big.Int, slot int64, bidAmount *big.Int, deadline *big.Int) (tx *types.Transaction, err error)
  213. AuctionMultiBid(amount *big.Int, startingSlot, endingSlot int64, slotSets [6]bool,
  214. maxBid, minBid, deadline *big.Int) (tx *types.Transaction, err error)
  215. // Forge
  216. AuctionCanForge(forger ethCommon.Address, blockNum int64) (bool, error)
  217. AuctionForge(forger ethCommon.Address) (*types.Transaction, error)
  218. // Fees
  219. AuctionClaimHEZ() (*types.Transaction, error)
  220. AuctionGetClaimableHEZ(bidder ethCommon.Address) (*big.Int, error)
  221. //
  222. // Smart Contract Status
  223. //
  224. AuctionConstants() (*common.AuctionConstants, error)
  225. AuctionEventsByBlock(blockNum int64, blockHash *ethCommon.Hash) (*AuctionEvents, error)
  226. AuctionEventInit() (*AuctionEventInitialize, int64, error)
  227. }
  228. //
  229. // Implementation
  230. //
  231. // AuctionClient is the implementation of the interface to the Auction Smart Contract in ethereum.
  232. type AuctionClient struct {
  233. client *EthereumClient
  234. chainID *big.Int
  235. address ethCommon.Address
  236. tokenHEZCfg TokenConfig
  237. auction *HermezAuctionProtocol.HermezAuctionProtocol
  238. tokenHEZ *HEZ.HEZ
  239. contractAbi abi.ABI
  240. opts *bind.CallOpts
  241. }
  242. // NewAuctionClient creates a new AuctionClient. `tokenAddress` is the address of the HEZ tokens.
  243. func NewAuctionClient(client *EthereumClient, address ethCommon.Address, tokenHEZCfg TokenConfig) (*AuctionClient, error) {
  244. contractAbi, err := abi.JSON(strings.NewReader(string(HermezAuctionProtocol.HermezAuctionProtocolABI)))
  245. if err != nil {
  246. return nil, tracerr.Wrap(err)
  247. }
  248. auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(address, client.Client())
  249. if err != nil {
  250. return nil, tracerr.Wrap(err)
  251. }
  252. tokenHEZ, err := HEZ.NewHEZ(tokenHEZCfg.Address, client.Client())
  253. if err != nil {
  254. return nil, tracerr.Wrap(err)
  255. }
  256. chainID, err := client.EthChainID()
  257. if err != nil {
  258. return nil, tracerr.Wrap(err)
  259. }
  260. return &AuctionClient{
  261. client: client,
  262. chainID: chainID,
  263. address: address,
  264. tokenHEZCfg: tokenHEZCfg,
  265. auction: auction,
  266. tokenHEZ: tokenHEZ,
  267. contractAbi: contractAbi,
  268. opts: newCallOpts(),
  269. }, nil
  270. }
  271. // AuctionSetSlotDeadline is the interface to call the smart contract function
  272. func (c *AuctionClient) AuctionSetSlotDeadline(newDeadline uint8) (*types.Transaction, error) {
  273. var tx *types.Transaction
  274. var err error
  275. if tx, err = c.client.CallAuth(
  276. 0,
  277. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  278. return c.auction.SetSlotDeadline(auth, newDeadline)
  279. },
  280. ); err != nil {
  281. return nil, tracerr.Wrap(fmt.Errorf("Failed setting slotDeadline: %w", err))
  282. }
  283. return tx, nil
  284. }
  285. // AuctionGetSlotDeadline is the interface to call the smart contract function
  286. func (c *AuctionClient) AuctionGetSlotDeadline() (slotDeadline uint8, err error) {
  287. if err := c.client.Call(func(ec *ethclient.Client) error {
  288. slotDeadline, err = c.auction.GetSlotDeadline(c.opts)
  289. return tracerr.Wrap(err)
  290. }); err != nil {
  291. return 0, tracerr.Wrap(err)
  292. }
  293. return slotDeadline, nil
  294. }
  295. // AuctionSetOpenAuctionSlots is the interface to call the smart contract function
  296. func (c *AuctionClient) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (tx *types.Transaction, err error) {
  297. if tx, err = c.client.CallAuth(
  298. 0,
  299. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  300. return c.auction.SetOpenAuctionSlots(auth, newOpenAuctionSlots)
  301. },
  302. ); err != nil {
  303. return nil, tracerr.Wrap(fmt.Errorf("Failed setting openAuctionSlots: %w", err))
  304. }
  305. return tx, nil
  306. }
  307. // AuctionGetOpenAuctionSlots is the interface to call the smart contract function
  308. func (c *AuctionClient) AuctionGetOpenAuctionSlots() (openAuctionSlots uint16, err error) {
  309. if err := c.client.Call(func(ec *ethclient.Client) error {
  310. openAuctionSlots, err = c.auction.GetOpenAuctionSlots(c.opts)
  311. return tracerr.Wrap(err)
  312. }); err != nil {
  313. return 0, tracerr.Wrap(err)
  314. }
  315. return openAuctionSlots, nil
  316. }
  317. // AuctionSetClosedAuctionSlots is the interface to call the smart contract function
  318. func (c *AuctionClient) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (tx *types.Transaction, err error) {
  319. if tx, err = c.client.CallAuth(
  320. 0,
  321. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  322. return c.auction.SetClosedAuctionSlots(auth, newClosedAuctionSlots)
  323. },
  324. ); err != nil {
  325. return nil, tracerr.Wrap(fmt.Errorf("Failed setting closedAuctionSlots: %w", err))
  326. }
  327. return tx, nil
  328. }
  329. // AuctionGetClosedAuctionSlots is the interface to call the smart contract function
  330. func (c *AuctionClient) AuctionGetClosedAuctionSlots() (closedAuctionSlots uint16, err error) {
  331. if err := c.client.Call(func(ec *ethclient.Client) error {
  332. closedAuctionSlots, err = c.auction.GetClosedAuctionSlots(c.opts)
  333. return tracerr.Wrap(err)
  334. }); err != nil {
  335. return 0, tracerr.Wrap(err)
  336. }
  337. return closedAuctionSlots, nil
  338. }
  339. // AuctionSetOutbidding is the interface to call the smart contract function
  340. func (c *AuctionClient) AuctionSetOutbidding(newOutbidding uint16) (tx *types.Transaction, err error) {
  341. if tx, err = c.client.CallAuth(
  342. 12500000, //nolint:gomnd
  343. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  344. return c.auction.SetOutbidding(auth, newOutbidding)
  345. },
  346. ); err != nil {
  347. return nil, tracerr.Wrap(fmt.Errorf("Failed setting setOutbidding: %w", err))
  348. }
  349. return tx, nil
  350. }
  351. // AuctionGetOutbidding is the interface to call the smart contract function
  352. func (c *AuctionClient) AuctionGetOutbidding() (outbidding uint16, err error) {
  353. if err := c.client.Call(func(ec *ethclient.Client) error {
  354. outbidding, err = c.auction.GetOutbidding(c.opts)
  355. return tracerr.Wrap(err)
  356. }); err != nil {
  357. return 0, tracerr.Wrap(err)
  358. }
  359. return outbidding, nil
  360. }
  361. // AuctionSetAllocationRatio is the interface to call the smart contract function
  362. func (c *AuctionClient) AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (tx *types.Transaction, err error) {
  363. if tx, err = c.client.CallAuth(
  364. 0,
  365. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  366. return c.auction.SetAllocationRatio(auth, newAllocationRatio)
  367. },
  368. ); err != nil {
  369. return nil, tracerr.Wrap(fmt.Errorf("Failed setting allocationRatio: %w", err))
  370. }
  371. return tx, nil
  372. }
  373. // AuctionGetAllocationRatio is the interface to call the smart contract function
  374. func (c *AuctionClient) AuctionGetAllocationRatio() (allocationRation [3]uint16, err error) {
  375. if err := c.client.Call(func(ec *ethclient.Client) error {
  376. allocationRation, err = c.auction.GetAllocationRatio(c.opts)
  377. return tracerr.Wrap(err)
  378. }); err != nil {
  379. return [3]uint16{}, tracerr.Wrap(err)
  380. }
  381. return allocationRation, nil
  382. }
  383. // AuctionSetDonationAddress is the interface to call the smart contract function
  384. func (c *AuctionClient) AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (tx *types.Transaction, err error) {
  385. if tx, err = c.client.CallAuth(
  386. 0,
  387. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  388. return c.auction.SetDonationAddress(auth, newDonationAddress)
  389. },
  390. ); err != nil {
  391. return nil, tracerr.Wrap(fmt.Errorf("Failed setting donationAddress: %w", err))
  392. }
  393. return tx, nil
  394. }
  395. // AuctionGetDonationAddress is the interface to call the smart contract function
  396. func (c *AuctionClient) AuctionGetDonationAddress() (donationAddress *ethCommon.Address, err error) {
  397. var _donationAddress ethCommon.Address
  398. if err := c.client.Call(func(ec *ethclient.Client) error {
  399. _donationAddress, err = c.auction.GetDonationAddress(c.opts)
  400. return tracerr.Wrap(err)
  401. }); err != nil {
  402. return nil, tracerr.Wrap(err)
  403. }
  404. return &_donationAddress, nil
  405. }
  406. // AuctionSetBootCoordinator is the interface to call the smart contract function
  407. func (c *AuctionClient) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address, newBootCoordinatorURL string) (tx *types.Transaction, err error) {
  408. if tx, err = c.client.CallAuth(
  409. 0,
  410. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  411. return c.auction.SetBootCoordinator(auth, newBootCoordinator, newBootCoordinatorURL)
  412. },
  413. ); err != nil {
  414. return nil, tracerr.Wrap(fmt.Errorf("Failed setting bootCoordinator: %w", err))
  415. }
  416. return tx, nil
  417. }
  418. // AuctionGetBootCoordinator is the interface to call the smart contract function
  419. func (c *AuctionClient) AuctionGetBootCoordinator() (bootCoordinator *ethCommon.Address, err error) {
  420. var _bootCoordinator ethCommon.Address
  421. if err := c.client.Call(func(ec *ethclient.Client) error {
  422. _bootCoordinator, err = c.auction.GetBootCoordinator(c.opts)
  423. return tracerr.Wrap(err)
  424. }); err != nil {
  425. return nil, tracerr.Wrap(err)
  426. }
  427. return &_bootCoordinator, nil
  428. }
  429. // AuctionChangeDefaultSlotSetBid is the interface to call the smart contract function
  430. func (c *AuctionClient) AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (tx *types.Transaction, err error) {
  431. if tx, err = c.client.CallAuth(
  432. 0,
  433. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  434. slotSetToSend := big.NewInt(slotSet)
  435. return c.auction.ChangeDefaultSlotSetBid(auth, slotSetToSend, newInitialMinBid)
  436. },
  437. ); err != nil {
  438. return nil, tracerr.Wrap(fmt.Errorf("Failed changing slotSet Bid: %w", err))
  439. }
  440. return tx, nil
  441. }
  442. // AuctionGetClaimableHEZ is the interface to call the smart contract function
  443. func (c *AuctionClient) AuctionGetClaimableHEZ(claimAddress ethCommon.Address) (claimableHEZ *big.Int, err error) {
  444. if err := c.client.Call(func(ec *ethclient.Client) error {
  445. claimableHEZ, err = c.auction.GetClaimableHEZ(c.opts, claimAddress)
  446. return tracerr.Wrap(err)
  447. }); err != nil {
  448. return nil, tracerr.Wrap(err)
  449. }
  450. return claimableHEZ, nil
  451. }
  452. // AuctionSetCoordinator is the interface to call the smart contract function
  453. func (c *AuctionClient) AuctionSetCoordinator(forger ethCommon.Address, coordinatorURL string) (tx *types.Transaction, err error) {
  454. if tx, err = c.client.CallAuth(
  455. 0,
  456. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  457. return c.auction.SetCoordinator(auth, forger, coordinatorURL)
  458. },
  459. ); err != nil {
  460. return nil, tracerr.Wrap(fmt.Errorf("Failed set coordinator: %w", err))
  461. }
  462. return tx, nil
  463. }
  464. // AuctionGetCurrentSlotNumber is the interface to call the smart contract function
  465. func (c *AuctionClient) AuctionGetCurrentSlotNumber() (currentSlotNumber int64, err error) {
  466. var _currentSlotNumber *big.Int
  467. if err := c.client.Call(func(ec *ethclient.Client) error {
  468. _currentSlotNumber, err = c.auction.GetCurrentSlotNumber(c.opts)
  469. return tracerr.Wrap(err)
  470. }); err != nil {
  471. return 0, tracerr.Wrap(err)
  472. }
  473. return _currentSlotNumber.Int64(), nil
  474. }
  475. // AuctionGetMinBidBySlot is the interface to call the smart contract function
  476. func (c *AuctionClient) AuctionGetMinBidBySlot(slot int64) (minBid *big.Int, err error) {
  477. if err := c.client.Call(func(ec *ethclient.Client) error {
  478. slotToSend := big.NewInt(slot)
  479. minBid, err = c.auction.GetMinBidBySlot(c.opts, slotToSend)
  480. return tracerr.Wrap(err)
  481. }); err != nil {
  482. return big.NewInt(0), tracerr.Wrap(err)
  483. }
  484. return minBid, nil
  485. }
  486. // AuctionGetSlotSet is the interface to call the smart contract function
  487. func (c *AuctionClient) AuctionGetSlotSet(slot int64) (slotSet *big.Int, err error) {
  488. if err := c.client.Call(func(ec *ethclient.Client) error {
  489. slotToSend := big.NewInt(slot)
  490. slotSet, err = c.auction.GetSlotSet(c.opts, slotToSend)
  491. return tracerr.Wrap(err)
  492. }); err != nil {
  493. return big.NewInt(0), tracerr.Wrap(err)
  494. }
  495. return slotSet, nil
  496. }
  497. // AuctionGetDefaultSlotSetBid is the interface to call the smart contract function
  498. func (c *AuctionClient) AuctionGetDefaultSlotSetBid(slotSet uint8) (minBidSlotSet *big.Int, err error) {
  499. if err := c.client.Call(func(ec *ethclient.Client) error {
  500. minBidSlotSet, err = c.auction.GetDefaultSlotSetBid(c.opts, slotSet)
  501. return tracerr.Wrap(err)
  502. }); err != nil {
  503. return big.NewInt(0), tracerr.Wrap(err)
  504. }
  505. return minBidSlotSet, nil
  506. }
  507. // AuctionGetSlotNumber is the interface to call the smart contract function
  508. func (c *AuctionClient) AuctionGetSlotNumber(blockNum int64) (slot int64, err error) {
  509. var _slot *big.Int
  510. if err := c.client.Call(func(ec *ethclient.Client) error {
  511. _slot, err = c.auction.GetSlotNumber(c.opts, big.NewInt(blockNum))
  512. return tracerr.Wrap(err)
  513. }); err != nil {
  514. return 0, tracerr.Wrap(err)
  515. }
  516. return _slot.Int64(), nil
  517. }
  518. // AuctionBid is the interface to call the smart contract function
  519. func (c *AuctionClient) AuctionBid(amount *big.Int, slot int64, bidAmount *big.Int, deadline *big.Int) (tx *types.Transaction, err error) {
  520. if tx, err = c.client.CallAuth(
  521. 0,
  522. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  523. owner := c.client.account.Address
  524. spender := c.address
  525. nonce, err := c.tokenHEZ.Nonces(c.opts, owner)
  526. if err != nil {
  527. return nil, tracerr.Wrap(err)
  528. }
  529. tokenName := c.tokenHEZCfg.Name
  530. tokenAddr := c.tokenHEZCfg.Address
  531. digest, _ := createPermitDigest(tokenAddr, owner, spender, c.chainID, amount, nonce, deadline, tokenName)
  532. signature, _ := c.client.ks.SignHash(*c.client.account, digest)
  533. permit := createPermit(owner, spender, amount, deadline, digest, signature)
  534. _slot := big.NewInt(slot)
  535. return c.auction.ProcessBid(auth, amount, _slot, bidAmount, permit)
  536. },
  537. ); err != nil {
  538. return nil, tracerr.Wrap(fmt.Errorf("Failed bid: %w", err))
  539. }
  540. return tx, nil
  541. }
  542. // AuctionMultiBid is the interface to call the smart contract function
  543. func (c *AuctionClient) AuctionMultiBid(amount *big.Int, startingSlot, endingSlot int64, slotSets [6]bool,
  544. maxBid, minBid, deadline *big.Int) (tx *types.Transaction, err error) {
  545. if tx, err = c.client.CallAuth(
  546. 1000000, //nolint:gomnd
  547. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  548. owner := c.client.account.Address
  549. spender := c.address
  550. nonce, err := c.tokenHEZ.Nonces(c.opts, owner)
  551. if err != nil {
  552. return nil, tracerr.Wrap(err)
  553. }
  554. tokenName := c.tokenHEZCfg.Name
  555. tokenAddr := c.tokenHEZCfg.Address
  556. digest, _ := createPermitDigest(tokenAddr, owner, spender, c.chainID, amount, nonce, deadline, tokenName)
  557. signature, _ := c.client.ks.SignHash(*c.client.account, digest)
  558. permit := createPermit(owner, spender, amount, deadline, digest, signature)
  559. _startingSlot := big.NewInt(startingSlot)
  560. _endingSlot := big.NewInt(endingSlot)
  561. return c.auction.ProcessMultiBid(auth, amount, _startingSlot, _endingSlot, slotSets, maxBid, minBid, permit)
  562. },
  563. ); err != nil {
  564. return nil, tracerr.Wrap(fmt.Errorf("Failed multibid: %w", err))
  565. }
  566. return tx, nil
  567. }
  568. // AuctionCanForge is the interface to call the smart contract function
  569. func (c *AuctionClient) AuctionCanForge(forger ethCommon.Address, blockNum int64) (canForge bool, err error) {
  570. if err := c.client.Call(func(ec *ethclient.Client) error {
  571. canForge, err = c.auction.CanForge(c.opts, forger, big.NewInt(blockNum))
  572. return tracerr.Wrap(err)
  573. }); err != nil {
  574. return false, tracerr.Wrap(err)
  575. }
  576. return canForge, nil
  577. }
  578. // AuctionClaimHEZ is the interface to call the smart contract function
  579. func (c *AuctionClient) AuctionClaimHEZ() (tx *types.Transaction, err error) {
  580. if tx, err = c.client.CallAuth(
  581. 0,
  582. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  583. return c.auction.ClaimHEZ(auth)
  584. },
  585. ); err != nil {
  586. return nil, tracerr.Wrap(fmt.Errorf("Failed claim HEZ: %w", err))
  587. }
  588. return tx, nil
  589. }
  590. // AuctionForge is the interface to call the smart contract function
  591. func (c *AuctionClient) AuctionForge(forger ethCommon.Address) (tx *types.Transaction, err error) {
  592. if tx, err = c.client.CallAuth(
  593. 0,
  594. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  595. return c.auction.Forge(auth, forger)
  596. },
  597. ); err != nil {
  598. return nil, tracerr.Wrap(fmt.Errorf("Failed forge: %w", err))
  599. }
  600. return tx, nil
  601. }
  602. // AuctionConstants returns the Constants of the Auction Smart Contract
  603. func (c *AuctionClient) AuctionConstants() (auctionConstants *common.AuctionConstants, err error) {
  604. auctionConstants = new(common.AuctionConstants)
  605. if err := c.client.Call(func(ec *ethclient.Client) error {
  606. auctionConstants.BlocksPerSlot, err = c.auction.BLOCKSPERSLOT(c.opts)
  607. if err != nil {
  608. return tracerr.Wrap(err)
  609. }
  610. genesisBlock, err := c.auction.GenesisBlock(c.opts)
  611. if err != nil {
  612. return tracerr.Wrap(err)
  613. }
  614. auctionConstants.GenesisBlockNum = genesisBlock.Int64()
  615. auctionConstants.HermezRollup, err = c.auction.HermezRollup(c.opts)
  616. if err != nil {
  617. return tracerr.Wrap(err)
  618. }
  619. auctionConstants.InitialMinimalBidding, err = c.auction.INITIALMINIMALBIDDING(c.opts)
  620. if err != nil {
  621. return tracerr.Wrap(err)
  622. }
  623. auctionConstants.GovernanceAddress, err = c.auction.GovernanceAddress(c.opts)
  624. if err != nil {
  625. return tracerr.Wrap(err)
  626. }
  627. auctionConstants.TokenHEZ, err = c.auction.TokenHEZ(c.opts)
  628. if err != nil {
  629. return tracerr.Wrap(err)
  630. }
  631. return nil
  632. }); err != nil {
  633. return nil, tracerr.Wrap(err)
  634. }
  635. return auctionConstants, nil
  636. }
  637. // AuctionVariables returns the variables of the Auction Smart Contract
  638. func (c *AuctionClient) AuctionVariables() (auctionVariables *common.AuctionVariables, err error) {
  639. auctionVariables = new(common.AuctionVariables)
  640. if err := c.client.Call(func(ec *ethclient.Client) error {
  641. auctionVariables.AllocationRatio, err = c.AuctionGetAllocationRatio()
  642. if err != nil {
  643. return tracerr.Wrap(err)
  644. }
  645. bootCoordinator, err := c.AuctionGetBootCoordinator()
  646. if err != nil {
  647. return tracerr.Wrap(err)
  648. }
  649. auctionVariables.BootCoordinator = *bootCoordinator
  650. auctionVariables.BootCoordinatorURL, err = c.auction.BootCoordinatorURL(c.opts)
  651. if err != nil {
  652. return tracerr.Wrap(err)
  653. }
  654. auctionVariables.ClosedAuctionSlots, err = c.AuctionGetClosedAuctionSlots()
  655. if err != nil {
  656. return tracerr.Wrap(err)
  657. }
  658. var defaultSlotSetBid [6]*big.Int
  659. for i := uint8(0); i < 6; i++ {
  660. bid, err := c.AuctionGetDefaultSlotSetBid(i)
  661. if err != nil {
  662. return tracerr.Wrap(err)
  663. }
  664. defaultSlotSetBid[i] = bid
  665. }
  666. auctionVariables.DefaultSlotSetBid = defaultSlotSetBid
  667. donationAddress, err := c.AuctionGetDonationAddress()
  668. if err != nil {
  669. return tracerr.Wrap(err)
  670. }
  671. auctionVariables.DonationAddress = *donationAddress
  672. auctionVariables.OpenAuctionSlots, err = c.AuctionGetOpenAuctionSlots()
  673. if err != nil {
  674. return tracerr.Wrap(err)
  675. }
  676. auctionVariables.Outbidding, err = c.AuctionGetOutbidding()
  677. if err != nil {
  678. return tracerr.Wrap(err)
  679. }
  680. auctionVariables.SlotDeadline, err = c.AuctionGetSlotDeadline()
  681. return tracerr.Wrap(err)
  682. }); err != nil {
  683. return nil, tracerr.Wrap(err)
  684. }
  685. return auctionVariables, nil
  686. }
  687. var (
  688. logAuctionNewBid = crypto.Keccak256Hash([]byte("NewBid(uint128,uint128,address)"))
  689. logAuctionNewSlotDeadline = crypto.Keccak256Hash([]byte("NewSlotDeadline(uint8)"))
  690. logAuctionNewClosedAuctionSlots = crypto.Keccak256Hash([]byte("NewClosedAuctionSlots(uint16)"))
  691. logAuctionNewOutbidding = crypto.Keccak256Hash([]byte("NewOutbidding(uint16)"))
  692. logAuctionNewDonationAddress = crypto.Keccak256Hash([]byte("NewDonationAddress(address)"))
  693. logAuctionNewBootCoordinator = crypto.Keccak256Hash([]byte("NewBootCoordinator(address,string)"))
  694. logAuctionNewOpenAuctionSlots = crypto.Keccak256Hash([]byte("NewOpenAuctionSlots(uint16)"))
  695. logAuctionNewAllocationRatio = crypto.Keccak256Hash([]byte("NewAllocationRatio(uint16[3])"))
  696. logAuctionSetCoordinator = crypto.Keccak256Hash([]byte("SetCoordinator(address,address,string)"))
  697. logAuctionNewForgeAllocated = crypto.Keccak256Hash([]byte("NewForgeAllocated(address,address,uint128,uint128,uint128,uint128)"))
  698. logAuctionNewDefaultSlotSetBid = crypto.Keccak256Hash([]byte("NewDefaultSlotSetBid(uint128,uint128)"))
  699. logAuctionNewForge = crypto.Keccak256Hash([]byte("NewForge(address,uint128)"))
  700. logAuctionHEZClaimed = crypto.Keccak256Hash([]byte("HEZClaimed(address,uint128)"))
  701. logAuctionInitialize = crypto.Keccak256Hash([]byte(
  702. "InitializeHermezAuctionProtocolEvent(address,address,string,uint16,uint8,uint16,uint16,uint16[3])"))
  703. )
  704. // AuctionEventInit returns the initialize event with its corresponding block number
  705. func (c *AuctionClient) AuctionEventInit() (*AuctionEventInitialize, int64, error) {
  706. query := ethereum.FilterQuery{
  707. Addresses: []ethCommon.Address{
  708. c.address,
  709. },
  710. Topics: [][]ethCommon.Hash{{logAuctionInitialize}},
  711. }
  712. logs, err := c.client.client.FilterLogs(context.Background(), query)
  713. if err != nil {
  714. return nil, 0, tracerr.Wrap(err)
  715. }
  716. if len(logs) != 1 {
  717. return nil, 0, tracerr.Wrap(fmt.Errorf("no event of type InitializeHermezAuctionProtocolEvent found"))
  718. }
  719. vLog := logs[0]
  720. if vLog.Topics[0] != logAuctionInitialize {
  721. return nil, 0, tracerr.Wrap(fmt.Errorf("event is not InitializeHermezAuctionProtocolEvent"))
  722. }
  723. var auctionInit AuctionEventInitialize
  724. if err := c.contractAbi.UnpackIntoInterface(&auctionInit,
  725. "InitializeHermezAuctionProtocolEvent", vLog.Data); err != nil {
  726. return nil, 0, tracerr.Wrap(err)
  727. }
  728. return &auctionInit, int64(vLog.BlockNumber), tracerr.Wrap(err)
  729. }
  730. // AuctionEventsByBlock returns the events in a block that happened in the
  731. // Auction Smart Contract.
  732. // To query by blockNum, set blockNum >= 0 and blockHash == nil.
  733. // To query by blockHash, set blockNum == -1 and blockHash != nil.
  734. // If there are no events in that block the result is nil.
  735. func (c *AuctionClient) AuctionEventsByBlock(blockNum int64,
  736. blockHash *ethCommon.Hash) (*AuctionEvents, error) {
  737. var auctionEvents AuctionEvents
  738. var blockNumBigInt *big.Int
  739. if blockNum >= 0 {
  740. blockNumBigInt = big.NewInt(blockNum)
  741. }
  742. query := ethereum.FilterQuery{
  743. BlockHash: blockHash,
  744. FromBlock: blockNumBigInt,
  745. ToBlock: blockNumBigInt,
  746. Addresses: []ethCommon.Address{
  747. c.address,
  748. },
  749. Topics: [][]ethCommon.Hash{},
  750. }
  751. logs, err := c.client.client.FilterLogs(context.TODO(), query)
  752. if err != nil {
  753. return nil, tracerr.Wrap(err)
  754. }
  755. if len(logs) == 0 {
  756. return nil, nil
  757. }
  758. for _, vLog := range logs {
  759. if blockHash != nil && vLog.BlockHash != *blockHash {
  760. log.Errorw("Block hash mismatch", "expected", blockHash.String(), "got", vLog.BlockHash.String())
  761. return nil, tracerr.Wrap(ErrBlockHashMismatchEvent)
  762. }
  763. switch vLog.Topics[0] {
  764. case logAuctionNewBid:
  765. var auxNewBid struct {
  766. Slot *big.Int
  767. BidAmount *big.Int
  768. Address ethCommon.Address
  769. }
  770. var newBid AuctionEventNewBid
  771. if err := c.contractAbi.UnpackIntoInterface(&auxNewBid, "NewBid", vLog.Data); err != nil {
  772. return nil, tracerr.Wrap(err)
  773. }
  774. newBid.BidAmount = auxNewBid.BidAmount
  775. newBid.Slot = new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
  776. newBid.Bidder = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
  777. auctionEvents.NewBid = append(auctionEvents.NewBid, newBid)
  778. case logAuctionNewSlotDeadline:
  779. var newSlotDeadline AuctionEventNewSlotDeadline
  780. if err := c.contractAbi.UnpackIntoInterface(&newSlotDeadline, "NewSlotDeadline", vLog.Data); err != nil {
  781. return nil, tracerr.Wrap(err)
  782. }
  783. auctionEvents.NewSlotDeadline = append(auctionEvents.NewSlotDeadline, newSlotDeadline)
  784. case logAuctionNewClosedAuctionSlots:
  785. var newClosedAuctionSlots AuctionEventNewClosedAuctionSlots
  786. if err := c.contractAbi.UnpackIntoInterface(&newClosedAuctionSlots, "NewClosedAuctionSlots", vLog.Data); err != nil {
  787. return nil, tracerr.Wrap(err)
  788. }
  789. auctionEvents.NewClosedAuctionSlots = append(auctionEvents.NewClosedAuctionSlots, newClosedAuctionSlots)
  790. case logAuctionNewOutbidding:
  791. var newOutbidding AuctionEventNewOutbidding
  792. if err := c.contractAbi.UnpackIntoInterface(&newOutbidding, "NewOutbidding", vLog.Data); err != nil {
  793. return nil, tracerr.Wrap(err)
  794. }
  795. auctionEvents.NewOutbidding = append(auctionEvents.NewOutbidding, newOutbidding)
  796. case logAuctionNewDonationAddress:
  797. var newDonationAddress AuctionEventNewDonationAddress
  798. newDonationAddress.NewDonationAddress = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  799. auctionEvents.NewDonationAddress = append(auctionEvents.NewDonationAddress, newDonationAddress)
  800. case logAuctionNewBootCoordinator:
  801. var newBootCoordinator AuctionEventNewBootCoordinator
  802. if err := c.contractAbi.UnpackIntoInterface(&newBootCoordinator, "NewBootCoordinator", vLog.Data); err != nil {
  803. return nil, tracerr.Wrap(err)
  804. }
  805. newBootCoordinator.NewBootCoordinator = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  806. auctionEvents.NewBootCoordinator = append(auctionEvents.NewBootCoordinator, newBootCoordinator)
  807. case logAuctionNewOpenAuctionSlots:
  808. var newOpenAuctionSlots AuctionEventNewOpenAuctionSlots
  809. if err := c.contractAbi.UnpackIntoInterface(&newOpenAuctionSlots, "NewOpenAuctionSlots", vLog.Data); err != nil {
  810. return nil, tracerr.Wrap(err)
  811. }
  812. auctionEvents.NewOpenAuctionSlots = append(auctionEvents.NewOpenAuctionSlots, newOpenAuctionSlots)
  813. case logAuctionNewAllocationRatio:
  814. var newAllocationRatio AuctionEventNewAllocationRatio
  815. if err := c.contractAbi.UnpackIntoInterface(&newAllocationRatio, "NewAllocationRatio", vLog.Data); err != nil {
  816. return nil, tracerr.Wrap(err)
  817. }
  818. auctionEvents.NewAllocationRatio = append(auctionEvents.NewAllocationRatio, newAllocationRatio)
  819. case logAuctionSetCoordinator:
  820. var setCoordinator AuctionEventSetCoordinator
  821. if err := c.contractAbi.UnpackIntoInterface(&setCoordinator, "SetCoordinator", vLog.Data); err != nil {
  822. return nil, tracerr.Wrap(err)
  823. }
  824. setCoordinator.BidderAddress = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  825. setCoordinator.ForgerAddress = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
  826. auctionEvents.SetCoordinator = append(auctionEvents.SetCoordinator, setCoordinator)
  827. case logAuctionNewForgeAllocated:
  828. var newForgeAllocated AuctionEventNewForgeAllocated
  829. if err := c.contractAbi.UnpackIntoInterface(&newForgeAllocated, "NewForgeAllocated", vLog.Data); err != nil {
  830. return nil, tracerr.Wrap(err)
  831. }
  832. newForgeAllocated.Bidder = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  833. newForgeAllocated.Forger = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
  834. newForgeAllocated.SlotToForge = new(big.Int).SetBytes(vLog.Topics[3][:]).Int64()
  835. auctionEvents.NewForgeAllocated = append(auctionEvents.NewForgeAllocated, newForgeAllocated)
  836. case logAuctionNewDefaultSlotSetBid:
  837. var auxNewDefaultSlotSetBid struct {
  838. SlotSet *big.Int
  839. NewInitialMinBid *big.Int
  840. }
  841. var newDefaultSlotSetBid AuctionEventNewDefaultSlotSetBid
  842. if err := c.contractAbi.UnpackIntoInterface(&auxNewDefaultSlotSetBid, "NewDefaultSlotSetBid", vLog.Data); err != nil {
  843. return nil, tracerr.Wrap(err)
  844. }
  845. newDefaultSlotSetBid.NewInitialMinBid = auxNewDefaultSlotSetBid.NewInitialMinBid
  846. newDefaultSlotSetBid.SlotSet = auxNewDefaultSlotSetBid.SlotSet.Int64()
  847. auctionEvents.NewDefaultSlotSetBid = append(auctionEvents.NewDefaultSlotSetBid, newDefaultSlotSetBid)
  848. case logAuctionNewForge:
  849. var newForge AuctionEventNewForge
  850. newForge.Forger = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  851. newForge.SlotToForge = new(big.Int).SetBytes(vLog.Topics[2][:]).Int64()
  852. auctionEvents.NewForge = append(auctionEvents.NewForge, newForge)
  853. case logAuctionHEZClaimed:
  854. var HEZClaimed AuctionEventHEZClaimed
  855. if err := c.contractAbi.UnpackIntoInterface(&HEZClaimed, "HEZClaimed", vLog.Data); err != nil {
  856. return nil, tracerr.Wrap(err)
  857. }
  858. HEZClaimed.Owner = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  859. auctionEvents.HEZClaimed = append(auctionEvents.HEZClaimed, HEZClaimed)
  860. }
  861. }
  862. return &auctionEvents, nil
  863. }