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.

1367 lines
39 KiB

  1. package test
  2. import (
  3. "context"
  4. "encoding/binary"
  5. "encoding/json"
  6. "fmt"
  7. "math/big"
  8. "reflect"
  9. "sync"
  10. "time"
  11. ethCommon "github.com/ethereum/go-ethereum/common"
  12. "github.com/ethereum/go-ethereum/core/types"
  13. "github.com/hermeznetwork/hermez-node/common"
  14. "github.com/hermeznetwork/hermez-node/eth"
  15. "github.com/hermeznetwork/hermez-node/log"
  16. "github.com/iden3/go-iden3-crypto/babyjub"
  17. "github.com/mitchellh/copystructure"
  18. )
  19. func init() {
  20. copystructure.Copiers[reflect.TypeOf(big.Int{})] =
  21. func(raw interface{}) (interface{}, error) {
  22. in := raw.(big.Int)
  23. out := new(big.Int).Set(&in)
  24. return *out, nil
  25. }
  26. }
  27. // RollupBlock stores all the data related to the Rollup SC from an ethereum block
  28. type RollupBlock struct {
  29. State eth.RollupState
  30. Vars eth.RollupVariables
  31. Events eth.RollupEvents
  32. Txs map[ethCommon.Hash]*types.Transaction
  33. Constants *eth.RollupPublicConstants
  34. Eth *EthereumBlock
  35. }
  36. func (r *RollupBlock) addTransaction(tx *types.Transaction) *types.Transaction {
  37. txHash := tx.Hash()
  38. r.Txs[txHash] = tx
  39. return tx
  40. }
  41. var (
  42. errBidClosed = fmt.Errorf("Bid has already been closed")
  43. errBidNotOpen = fmt.Errorf("Bid has not been opened yet")
  44. errBidBelowMin = fmt.Errorf("Bid below minimum")
  45. errCoordNotReg = fmt.Errorf("Coordinator not registered")
  46. )
  47. // AuctionBlock stores all the data related to the Auction SC from an ethereum block
  48. type AuctionBlock struct {
  49. State eth.AuctionState
  50. Vars eth.AuctionVariables
  51. Events eth.AuctionEvents
  52. Txs map[ethCommon.Hash]*types.Transaction
  53. Constants *eth.AuctionConstants
  54. Eth *EthereumBlock
  55. }
  56. func (a *AuctionBlock) addTransaction(tx *types.Transaction) *types.Transaction {
  57. txHash := tx.Hash()
  58. a.Txs[txHash] = tx
  59. return tx
  60. }
  61. func (a *AuctionBlock) getSlotNumber(blockNumber int64) int64 {
  62. if a.Eth.BlockNum >= a.Constants.GenesisBlockNum {
  63. return (blockNumber - a.Constants.GenesisBlockNum) / int64(a.Constants.BlocksPerSlot)
  64. }
  65. return 0
  66. }
  67. func (a *AuctionBlock) getCurrentSlotNumber() int64 {
  68. return a.getSlotNumber(a.Eth.BlockNum)
  69. }
  70. func (a *AuctionBlock) getSlotSet(slot int64) int64 {
  71. return slot % int64(len(a.Vars.DefaultSlotSetBid))
  72. }
  73. func (a *AuctionBlock) getMinBidBySlot(slot int64) (*big.Int, error) {
  74. if slot < a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots) {
  75. return nil, errBidClosed
  76. }
  77. slotSet := a.getSlotSet(slot)
  78. // fmt.Println("slot:", slot, "slotSet:", slotSet)
  79. var prevBid *big.Int
  80. slotState, ok := a.State.Slots[slot]
  81. if !ok {
  82. slotState = eth.NewSlotState()
  83. a.State.Slots[slot] = slotState
  84. }
  85. // If the bidAmount for a slot is 0 it means that it has not yet been bid, so the midBid will be the minimum
  86. // bid for the slot time plus the outbidding set, otherwise it will be the bidAmount plus the outbidding
  87. if slotState.BidAmount.Cmp(big.NewInt(0)) == 0 {
  88. prevBid = a.Vars.DefaultSlotSetBid[slotSet]
  89. } else {
  90. prevBid = slotState.BidAmount
  91. }
  92. outBid := new(big.Int).Set(prevBid)
  93. // fmt.Println("outBid:", outBid)
  94. outBid.Mul(outBid, big.NewInt(int64(a.Vars.Outbidding)))
  95. outBid.Div(outBid, big.NewInt(10000)) //nolint:gomnd
  96. outBid.Add(prevBid, outBid)
  97. // fmt.Println("minBid:", outBid)
  98. return outBid, nil
  99. }
  100. func (a *AuctionBlock) forge(forger ethCommon.Address) error {
  101. if ok, err := a.canForge(forger, a.Eth.BlockNum); err != nil {
  102. return err
  103. } else if !ok {
  104. return fmt.Errorf("Can't forge")
  105. }
  106. slotToForge := a.getSlotNumber(a.Eth.BlockNum)
  107. slotState, ok := a.State.Slots[slotToForge]
  108. if !ok {
  109. slotState = eth.NewSlotState()
  110. a.State.Slots[slotToForge] = slotState
  111. }
  112. slotState.Fulfilled = true
  113. a.Events.NewForge = append(a.Events.NewForge, eth.AuctionEventNewForge{
  114. Forger: forger,
  115. SlotToForge: slotToForge,
  116. })
  117. return nil
  118. }
  119. func (a *AuctionBlock) canForge(forger ethCommon.Address, blockNum int64) (bool, error) {
  120. if blockNum < a.Constants.GenesisBlockNum {
  121. return false, fmt.Errorf("Auction has not started yet")
  122. }
  123. slotToForge := a.getSlotNumber(blockNum)
  124. // Get the relativeBlock to check if the slotDeadline has been exceeded
  125. relativeBlock := blockNum - (a.Constants.GenesisBlockNum + (slotToForge * int64(a.Constants.BlocksPerSlot)))
  126. // If the closedMinBid is 0 it means that we have to take as minBid the one that is set for this slot set,
  127. // otherwise the one that has been saved will be used
  128. var minBid *big.Int
  129. slotState, ok := a.State.Slots[slotToForge]
  130. if !ok {
  131. slotState = eth.NewSlotState()
  132. a.State.Slots[slotToForge] = slotState
  133. }
  134. if slotState.ClosedMinBid.Cmp(big.NewInt(0)) == 0 {
  135. minBid = a.Vars.DefaultSlotSetBid[a.getSlotSet(slotToForge)]
  136. } else {
  137. minBid = slotState.ClosedMinBid
  138. }
  139. if !slotState.Fulfilled && (relativeBlock >= int64(a.Vars.SlotDeadline)) {
  140. // if the relative block has exceeded the slotDeadline and no batch has been forged, anyone can forge
  141. return true, nil
  142. // TODO, find the forger set by the Bidder
  143. } else if coord, ok := a.State.Coordinators[slotState.Bidder]; ok &&
  144. coord.Forger == forger && slotState.BidAmount.Cmp(minBid) >= 0 {
  145. // if forger bidAmount has exceeded the minBid it can forge
  146. return true, nil
  147. } else if a.Vars.BootCoordinator == forger && slotState.BidAmount.Cmp(minBid) == -1 {
  148. // if it's the boot coordinator and it has not been bid or the bid is below the minimum it can forge
  149. return true, nil
  150. } else {
  151. return false, nil
  152. }
  153. }
  154. // EthereumBlock stores all the generic data related to the an ethereum block
  155. type EthereumBlock struct {
  156. BlockNum int64
  157. Time int64
  158. Hash ethCommon.Hash
  159. ParentHash ethCommon.Hash
  160. Tokens map[ethCommon.Address]eth.ERC20Consts
  161. // state ethState
  162. }
  163. // Block represents a ethereum block
  164. type Block struct {
  165. Rollup *RollupBlock
  166. Auction *AuctionBlock
  167. Eth *EthereumBlock
  168. }
  169. func (b *Block) copy() *Block {
  170. bCopyRaw, err := copystructure.Copy(b)
  171. if err != nil {
  172. panic(err)
  173. }
  174. bCopy := bCopyRaw.(*Block)
  175. return bCopy
  176. }
  177. // Next prepares the successive block.
  178. func (b *Block) Next() *Block {
  179. blockNext := b.copy()
  180. blockNext.Rollup.Events = eth.NewRollupEvents()
  181. blockNext.Auction.Events = eth.NewAuctionEvents()
  182. blockNext.Eth.BlockNum = b.Eth.BlockNum + 1
  183. blockNext.Eth.ParentHash = b.Eth.Hash
  184. blockNext.Rollup.Constants = b.Rollup.Constants
  185. blockNext.Auction.Constants = b.Auction.Constants
  186. blockNext.Rollup.Eth = blockNext.Eth
  187. blockNext.Auction.Eth = blockNext.Eth
  188. return blockNext
  189. }
  190. // ClientSetup is used to initialize the constants of the Smart Contracts and
  191. // other details of the test Client
  192. type ClientSetup struct {
  193. RollupConstants *eth.RollupPublicConstants
  194. RollupVariables *eth.RollupVariables
  195. AuctionConstants *eth.AuctionConstants
  196. AuctionVariables *eth.AuctionVariables
  197. VerifyProof bool
  198. }
  199. // NewClientSetupExample returns a ClientSetup example with hardcoded realistic values.
  200. //nolint:gomnd
  201. func NewClientSetupExample() *ClientSetup {
  202. // rfield, ok := new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)
  203. // if !ok {
  204. // panic("bad rfield")
  205. // }
  206. initialMinimalBidding, ok := new(big.Int).SetString("10000000000000000000", 10) // 10 * (1e18)
  207. if !ok {
  208. panic("bad initialMinimalBidding")
  209. }
  210. tokenHEZ := ethCommon.HexToAddress("0x51D243D62852Bba334DD5cc33f242BAc8c698074")
  211. governanceAddress := ethCommon.HexToAddress("0x688EfD95BA4391f93717CF02A9aED9DBD2855cDd")
  212. rollupConstants := &eth.RollupPublicConstants{
  213. Verifiers: []eth.RollupVerifierStruct{
  214. {
  215. MaxTx: 2048,
  216. NLevels: 32,
  217. },
  218. },
  219. TokenHEZ: tokenHEZ,
  220. HermezGovernanceDAOAddress: governanceAddress,
  221. SafetyAddress: ethCommon.HexToAddress("0x84d8B79E84fe87B14ad61A554e740f6736bF4c20"),
  222. HermezAuctionContract: ethCommon.HexToAddress("0x8E442975805fb1908f43050c9C1A522cB0e28D7b"),
  223. WithdrawDelayerContract: ethCommon.HexToAddress("0x5CB7979cBdbf65719BEE92e4D15b7b7Ed3D79114"),
  224. }
  225. rollupVariables := &eth.RollupVariables{
  226. FeeAddToken: big.NewInt(11),
  227. ForgeL1L2BatchTimeout: 9,
  228. WithdrawalDelay: 80,
  229. }
  230. auctionConstants := &eth.AuctionConstants{
  231. BlocksPerSlot: 40,
  232. InitialMinimalBidding: initialMinimalBidding,
  233. GenesisBlockNum: 0,
  234. GovernanceAddress: governanceAddress,
  235. TokenHEZ: tokenHEZ,
  236. HermezRollup: ethCommon.HexToAddress("0x474B6e29852257491cf283EfB1A9C61eBFe48369"),
  237. }
  238. auctionVariables := &eth.AuctionVariables{
  239. DonationAddress: ethCommon.HexToAddress("0x61Ed87CF0A1496b49A420DA6D84B58196b98f2e7"),
  240. BootCoordinator: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
  241. DefaultSlotSetBid: [6]*big.Int{
  242. big.NewInt(1000), big.NewInt(1100), big.NewInt(1200),
  243. big.NewInt(1300), big.NewInt(1400), big.NewInt(1500)},
  244. ClosedAuctionSlots: 2,
  245. OpenAuctionSlots: 4320,
  246. AllocationRatio: [3]uint16{4000, 4000, 2000},
  247. Outbidding: 1000,
  248. SlotDeadline: 20,
  249. }
  250. return &ClientSetup{
  251. RollupConstants: rollupConstants,
  252. RollupVariables: rollupVariables,
  253. AuctionConstants: auctionConstants,
  254. AuctionVariables: auctionVariables,
  255. }
  256. }
  257. // Timer is an interface to simulate a source of time, useful to advance time
  258. // virtually.
  259. type Timer interface {
  260. Time() int64
  261. }
  262. // type forgeBatchArgs struct {
  263. // ethTx *types.Transaction
  264. // blockNum int64
  265. // blockHash ethCommon.Hash
  266. // }
  267. // Client implements the eth.ClientInterface interface, allowing to manipulate the
  268. // values for testing, working with deterministic results.
  269. type Client struct {
  270. rw *sync.RWMutex
  271. log bool
  272. addr *ethCommon.Address
  273. rollupConstants *eth.RollupPublicConstants
  274. auctionConstants *eth.AuctionConstants
  275. blocks map[int64]*Block
  276. // state state
  277. blockNum int64 // last mined block num
  278. maxBlockNum int64 // highest block num calculated
  279. timer Timer
  280. hasher hasher
  281. forgeBatchArgsPending map[ethCommon.Hash]*eth.RollupForgeBatchArgs
  282. forgeBatchArgs map[ethCommon.Hash]*eth.RollupForgeBatchArgs
  283. }
  284. // NewClient returns a new test Client that implements the eth.IClient
  285. // interface, at the given initialBlockNumber.
  286. func NewClient(l bool, timer Timer, addr *ethCommon.Address, setup *ClientSetup) *Client {
  287. blocks := make(map[int64]*Block)
  288. blockNum := int64(0)
  289. hasher := hasher{}
  290. // Add ethereum genesis block
  291. mapL1TxQueue := make(map[int64]*eth.QueueStruct)
  292. mapL1TxQueue[0] = eth.NewQueueStruct()
  293. mapL1TxQueue[1] = eth.NewQueueStruct()
  294. blockCurrent := Block{
  295. Rollup: &RollupBlock{
  296. State: eth.RollupState{
  297. StateRoot: big.NewInt(0),
  298. ExitRoots: make([]*big.Int, 0),
  299. ExitNullifierMap: make(map[[256 / 8]byte]bool),
  300. // TokenID = 0 is ETH. Set first entry in TokenList with 0x0 address for ETH.
  301. TokenList: []ethCommon.Address{{}},
  302. TokenMap: make(map[ethCommon.Address]bool),
  303. MapL1TxQueue: mapL1TxQueue,
  304. LastL1L2Batch: 0,
  305. CurrentToForgeL1TxsNum: 0,
  306. LastToForgeL1TxsNum: 1,
  307. CurrentIdx: 0,
  308. },
  309. Vars: *setup.RollupVariables,
  310. Txs: make(map[ethCommon.Hash]*types.Transaction),
  311. Events: eth.NewRollupEvents(),
  312. Constants: setup.RollupConstants,
  313. },
  314. Auction: &AuctionBlock{
  315. State: eth.AuctionState{
  316. Slots: make(map[int64]*eth.SlotState),
  317. PendingBalances: make(map[ethCommon.Address]*big.Int),
  318. Coordinators: make(map[ethCommon.Address]*eth.Coordinator),
  319. },
  320. Vars: *setup.AuctionVariables,
  321. Txs: make(map[ethCommon.Hash]*types.Transaction),
  322. Events: eth.NewAuctionEvents(),
  323. Constants: setup.AuctionConstants,
  324. },
  325. Eth: &EthereumBlock{
  326. BlockNum: blockNum,
  327. Time: timer.Time(),
  328. Hash: hasher.Next(),
  329. ParentHash: ethCommon.Hash{},
  330. Tokens: make(map[ethCommon.Address]eth.ERC20Consts),
  331. },
  332. }
  333. blockCurrent.Rollup.Eth = blockCurrent.Eth
  334. blockCurrent.Auction.Eth = blockCurrent.Eth
  335. blocks[blockNum] = &blockCurrent
  336. blockNext := blockCurrent.Next()
  337. blocks[blockNum+1] = blockNext
  338. return &Client{
  339. rw: &sync.RWMutex{},
  340. log: l,
  341. addr: addr,
  342. rollupConstants: setup.RollupConstants,
  343. auctionConstants: setup.AuctionConstants,
  344. blocks: blocks,
  345. timer: timer,
  346. hasher: hasher,
  347. forgeBatchArgsPending: make(map[ethCommon.Hash]*eth.RollupForgeBatchArgs),
  348. forgeBatchArgs: make(map[ethCommon.Hash]*eth.RollupForgeBatchArgs),
  349. }
  350. }
  351. //
  352. // Mock Control
  353. //
  354. func (c *Client) setNextBlock(block *Block) {
  355. c.blocks[c.blockNum+1] = block
  356. }
  357. func (c *Client) revertIfErr(err error, block *Block) {
  358. if err != nil {
  359. log.Infow("TestClient revert", "block", block.Eth.BlockNum, "err", err)
  360. c.setNextBlock(block)
  361. }
  362. }
  363. // Debugf calls log.Debugf if c.log is true
  364. func (c *Client) Debugf(template string, args ...interface{}) {
  365. if c.log {
  366. log.Debugf(template, args...)
  367. }
  368. }
  369. // Debugw calls log.Debugw if c.log is true
  370. func (c *Client) Debugw(template string, kv ...interface{}) {
  371. if c.log {
  372. log.Debugw(template, kv...)
  373. }
  374. }
  375. type hasher struct {
  376. counter uint64
  377. }
  378. // Next returns the next hash
  379. func (h *hasher) Next() ethCommon.Hash {
  380. var hash ethCommon.Hash
  381. binary.LittleEndian.PutUint64(hash[:], h.counter)
  382. h.counter++
  383. return hash
  384. }
  385. func (c *Client) nextBlock() *Block {
  386. return c.blocks[c.blockNum+1]
  387. }
  388. func (c *Client) currentBlock() *Block {
  389. return c.blocks[c.blockNum]
  390. }
  391. // CtlSetAddr sets the address of the client
  392. func (c *Client) CtlSetAddr(addr ethCommon.Address) {
  393. c.addr = &addr
  394. }
  395. // CtlMineBlock moves one block forward
  396. func (c *Client) CtlMineBlock() {
  397. c.rw.Lock()
  398. defer c.rw.Unlock()
  399. blockCurrent := c.nextBlock()
  400. c.blockNum++
  401. c.maxBlockNum = c.blockNum
  402. blockCurrent.Eth.Time = c.timer.Time()
  403. blockCurrent.Eth.Hash = c.hasher.Next()
  404. for ethTxHash, forgeBatchArgs := range c.forgeBatchArgsPending {
  405. c.forgeBatchArgs[ethTxHash] = forgeBatchArgs
  406. }
  407. c.forgeBatchArgsPending = make(map[ethCommon.Hash]*eth.RollupForgeBatchArgs)
  408. blockNext := blockCurrent.Next()
  409. c.blocks[c.blockNum+1] = blockNext
  410. c.Debugw("TestClient mined block", "blockNum", c.blockNum)
  411. }
  412. // CtlRollback discards the last mined block. Use this to replace a mined
  413. // block to simulate reorgs.
  414. func (c *Client) CtlRollback() {
  415. c.rw.Lock()
  416. defer c.rw.Unlock()
  417. if c.blockNum == 0 {
  418. panic("Can't rollback at blockNum = 0")
  419. }
  420. delete(c.blocks, c.blockNum+1) // delete next block
  421. delete(c.blocks, c.blockNum) // delete current block
  422. c.blockNum--
  423. blockCurrent := c.blocks[c.blockNum]
  424. blockNext := blockCurrent.Next()
  425. c.blocks[c.blockNum+1] = blockNext
  426. }
  427. //
  428. // Ethereum
  429. //
  430. // EthCurrentBlock returns the current blockNum
  431. func (c *Client) EthCurrentBlock() (int64, error) {
  432. c.rw.RLock()
  433. defer c.rw.RUnlock()
  434. if c.blockNum < c.maxBlockNum {
  435. panic("blockNum has decreased. " +
  436. "After a rollback you must mine to reach the same or higher blockNum")
  437. }
  438. return c.blockNum, nil
  439. }
  440. // EthTransactionReceipt returns the transaction receipt of the given txHash
  441. func (c *Client) EthTransactionReceipt(ctx context.Context, txHash ethCommon.Hash) (*types.Receipt, error) {
  442. c.rw.RLock()
  443. defer c.rw.RUnlock()
  444. for i := int64(0); i < c.blockNum; i++ {
  445. b := c.blocks[i]
  446. _, ok := b.Rollup.Txs[txHash]
  447. if !ok {
  448. _, ok = b.Auction.Txs[txHash]
  449. }
  450. if ok {
  451. return &types.Receipt{
  452. TxHash: txHash,
  453. Status: types.ReceiptStatusSuccessful,
  454. BlockHash: b.Eth.Hash,
  455. BlockNumber: big.NewInt(b.Eth.BlockNum),
  456. }, nil
  457. }
  458. }
  459. return nil, nil
  460. }
  461. // CtlAddERC20 adds an ERC20 token to the blockchain.
  462. func (c *Client) CtlAddERC20(tokenAddr ethCommon.Address, constants eth.ERC20Consts) {
  463. nextBlock := c.nextBlock()
  464. e := nextBlock.Eth
  465. e.Tokens[tokenAddr] = constants
  466. }
  467. // EthERC20Consts returns the constants defined for a particular ERC20 Token instance.
  468. func (c *Client) EthERC20Consts(tokenAddr ethCommon.Address) (*eth.ERC20Consts, error) {
  469. currentBlock := c.currentBlock()
  470. e := currentBlock.Eth
  471. if constants, ok := e.Tokens[tokenAddr]; ok {
  472. return &constants, nil
  473. }
  474. return nil, fmt.Errorf("tokenAddr not found")
  475. }
  476. // func newHeader(number *big.Int) *types.Header {
  477. // return &types.Header{
  478. // Number: number,
  479. // Time: uint64(number.Int64()),
  480. // }
  481. // }
  482. // EthHeaderByNumber returns the *types.Header for the given block number in a
  483. // deterministic way.
  484. // func (c *Client) EthHeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
  485. // return newHeader(number), nil
  486. // }
  487. // EthBlockByNumber returns the *common.Block for the given block number in a
  488. // deterministic way.
  489. func (c *Client) EthBlockByNumber(ctx context.Context, blockNum int64) (*common.Block, error) {
  490. c.rw.RLock()
  491. defer c.rw.RUnlock()
  492. block, ok := c.blocks[blockNum]
  493. if !ok {
  494. return nil, fmt.Errorf("block not found")
  495. }
  496. return &common.Block{
  497. EthBlockNum: blockNum,
  498. Timestamp: time.Unix(block.Eth.Time, 0),
  499. Hash: block.Eth.Hash,
  500. ParentHash: block.Eth.ParentHash,
  501. }, nil
  502. }
  503. // EthAddress returns the ethereum address of the account loaded into the Client
  504. func (c *Client) EthAddress() (*ethCommon.Address, error) {
  505. if c.addr == nil {
  506. return nil, eth.ErrAccountNil
  507. }
  508. return c.addr, nil
  509. }
  510. var errTODO = fmt.Errorf("TODO: Not implemented yet")
  511. //
  512. // Rollup
  513. //
  514. // CtlAddL1TxUser adds an L1TxUser to the L1UserTxs queue of the Rollup
  515. func (c *Client) CtlAddL1TxUser(l1Tx *common.L1Tx) {
  516. c.rw.Lock()
  517. defer c.rw.Unlock()
  518. nextBlock := c.nextBlock()
  519. r := nextBlock.Rollup
  520. queue := r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
  521. if len(queue.L1TxQueue) >= eth.RollupConstMaxL1UserTx {
  522. r.State.LastToForgeL1TxsNum++
  523. r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
  524. queue = r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
  525. }
  526. if l1Tx.FromIdx != nil && int64(*l1Tx.FromIdx) > r.State.CurrentIdx {
  527. panic("l1Tx.FromIdx > r.State.CurrentIdx")
  528. }
  529. if int(l1Tx.TokenID)+1 > len(r.State.TokenList) {
  530. panic("l1Tx.TokenID + 1 > len(r.State.TokenList)")
  531. }
  532. queue.L1TxQueue = append(queue.L1TxQueue, *l1Tx)
  533. r.Events.L1UserTx = append(r.Events.L1UserTx, eth.RollupEventL1UserTx{
  534. L1Tx: *l1Tx,
  535. ToForgeL1TxsNum: r.State.LastToForgeL1TxsNum,
  536. Position: len(queue.L1TxQueue) - 1,
  537. })
  538. }
  539. type transactionData struct {
  540. Name string
  541. Value interface{}
  542. }
  543. func newTransaction(name string, value interface{}) *types.Transaction {
  544. data, err := json.Marshal(transactionData{name, value})
  545. if err != nil {
  546. panic(err)
  547. }
  548. return types.NewTransaction(0, ethCommon.Address{}, nil, 0, nil,
  549. data)
  550. }
  551. // RollupForgeBatch is the interface to call the smart contract function
  552. func (c *Client) RollupForgeBatch(args *eth.RollupForgeBatchArgs) (tx *types.Transaction, err error) {
  553. c.rw.Lock()
  554. defer c.rw.Unlock()
  555. cpy := c.nextBlock().copy()
  556. defer func() { c.revertIfErr(err, cpy) }()
  557. if c.addr == nil {
  558. return nil, eth.ErrAccountNil
  559. }
  560. a := c.nextBlock().Auction
  561. ok, err := a.canForge(*c.addr, a.Eth.BlockNum)
  562. if err != nil {
  563. return nil, err
  564. }
  565. if !ok {
  566. return nil, fmt.Errorf("incorrect slot")
  567. }
  568. // TODO: Verify proof
  569. // Auction
  570. err = a.forge(*c.addr)
  571. if err != nil {
  572. return nil, err
  573. }
  574. // TODO: If successful, store the tx in a successful array.
  575. // TODO: If failed, store the tx in a failed array.
  576. // TODO: Add method to move the tx to another block, reapply it there, and possibly go from successful to failed.
  577. return c.addBatch(args)
  578. }
  579. // CtlAddBatch adds forged batch to the Rollup, without checking any ZKProof
  580. func (c *Client) CtlAddBatch(args *eth.RollupForgeBatchArgs) {
  581. c.rw.Lock()
  582. defer c.rw.Unlock()
  583. if _, err := c.addBatch(args); err != nil {
  584. panic(err)
  585. }
  586. }
  587. func (c *Client) addBatch(args *eth.RollupForgeBatchArgs) (*types.Transaction, error) {
  588. nextBlock := c.nextBlock()
  589. r := nextBlock.Rollup
  590. r.State.StateRoot = args.NewStRoot
  591. if args.NewLastIdx < r.State.CurrentIdx {
  592. return nil, fmt.Errorf("args.NewLastIdx < r.State.CurrentIdx")
  593. }
  594. r.State.CurrentIdx = args.NewLastIdx
  595. r.State.ExitRoots = append(r.State.ExitRoots, args.NewExitRoot)
  596. if args.L1Batch {
  597. r.State.CurrentToForgeL1TxsNum++
  598. if r.State.CurrentToForgeL1TxsNum == r.State.LastToForgeL1TxsNum {
  599. r.State.LastToForgeL1TxsNum++
  600. r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
  601. }
  602. }
  603. ethTx := r.addTransaction(newTransaction("forgebatch", args))
  604. c.forgeBatchArgsPending[ethTx.Hash()] = args
  605. r.Events.ForgeBatch = append(r.Events.ForgeBatch, eth.RollupEventForgeBatch{
  606. BatchNum: int64(len(r.State.ExitRoots)),
  607. EthTxHash: ethTx.Hash(),
  608. })
  609. return ethTx, nil
  610. }
  611. // RollupAddToken is the interface to call the smart contract function
  612. func (c *Client) RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int) (tx *types.Transaction, err error) {
  613. c.rw.Lock()
  614. defer c.rw.Unlock()
  615. cpy := c.nextBlock().copy()
  616. defer func() { c.revertIfErr(err, cpy) }()
  617. if c.addr == nil {
  618. return nil, eth.ErrAccountNil
  619. }
  620. nextBlock := c.nextBlock()
  621. r := nextBlock.Rollup
  622. if _, ok := r.State.TokenMap[tokenAddress]; ok {
  623. return nil, fmt.Errorf("Token %v already registered", tokenAddress)
  624. }
  625. if feeAddToken.Cmp(r.Vars.FeeAddToken) != 0 {
  626. return nil, fmt.Errorf("Expected fee: %v but got: %v", r.Vars.FeeAddToken, feeAddToken)
  627. }
  628. r.State.TokenMap[tokenAddress] = true
  629. r.State.TokenList = append(r.State.TokenList, tokenAddress)
  630. r.Events.AddToken = append(r.Events.AddToken, eth.RollupEventAddToken{Address: tokenAddress,
  631. TokenID: uint32(len(r.State.TokenList) - 1)})
  632. return r.addTransaction(newTransaction("addtoken", tokenAddress)), nil
  633. }
  634. // RollupWithdrawSNARK is the interface to call the smart contract function
  635. // func (c *Client) RollupWithdrawSNARK() (*types.Transaction, error) { // TODO (Not defined in Hermez.sol)
  636. // return nil, errTODO
  637. // }
  638. // RollupWithdraw is the interface to call the smart contract function
  639. func (c *Client) RollupWithdraw(tokenID int64, balance *big.Int, babyPubKey *babyjub.PublicKey, numExitRoot int64, siblings []*big.Int, idx int64, instantWithdraw bool) (tx *types.Transaction, err error) {
  640. c.rw.Lock()
  641. defer c.rw.Unlock()
  642. cpy := c.nextBlock().copy()
  643. defer func() { c.revertIfErr(err, cpy) }()
  644. if c.addr == nil {
  645. return nil, eth.ErrAccountNil
  646. }
  647. log.Error("TODO")
  648. return nil, errTODO
  649. }
  650. // RollupForceExit is the interface to call the smart contract function
  651. func (c *Client) RollupForceExit(fromIdx int64, amountF common.Float16, tokenID int64) (tx *types.Transaction, err error) {
  652. c.rw.Lock()
  653. defer c.rw.Unlock()
  654. cpy := c.nextBlock().copy()
  655. defer func() { c.revertIfErr(err, cpy) }()
  656. if c.addr == nil {
  657. return nil, eth.ErrAccountNil
  658. }
  659. log.Error("TODO")
  660. return nil, errTODO
  661. }
  662. // RollupForceTransfer is the interface to call the smart contract function
  663. func (c *Client) RollupForceTransfer(fromIdx int64, amountF common.Float16, tokenID, toIdx int64) (tx *types.Transaction, err error) {
  664. c.rw.Lock()
  665. defer c.rw.Unlock()
  666. cpy := c.nextBlock().copy()
  667. defer func() { c.revertIfErr(err, cpy) }()
  668. if c.addr == nil {
  669. return nil, eth.ErrAccountNil
  670. }
  671. log.Error("TODO")
  672. return nil, errTODO
  673. }
  674. // RollupCreateAccountDepositTransfer is the interface to call the smart contract function
  675. func (c *Client) RollupCreateAccountDepositTransfer(babyPubKey babyjub.PublicKey, loadAmountF, amountF common.Float16, tokenID int64, toIdx int64) (tx *types.Transaction, err error) {
  676. c.rw.Lock()
  677. defer c.rw.Unlock()
  678. cpy := c.nextBlock().copy()
  679. defer func() { c.revertIfErr(err, cpy) }()
  680. if c.addr == nil {
  681. return nil, eth.ErrAccountNil
  682. }
  683. log.Error("TODO")
  684. return nil, errTODO
  685. }
  686. // RollupGetCurrentTokens is the interface to call the smart contract function
  687. func (c *Client) RollupGetCurrentTokens() (*big.Int, error) {
  688. c.rw.RLock()
  689. defer c.rw.RUnlock()
  690. log.Error("TODO")
  691. return nil, errTODO
  692. }
  693. // RollupDepositTransfer is the interface to call the smart contract function
  694. func (c *Client) RollupDepositTransfer(fromIdx int64, loadAmountF, amountF common.Float16, tokenID int64, toIdx int64) (tx *types.Transaction, err error) {
  695. c.rw.Lock()
  696. defer c.rw.Unlock()
  697. cpy := c.nextBlock().copy()
  698. defer func() { c.revertIfErr(err, cpy) }()
  699. if c.addr == nil {
  700. return nil, eth.ErrAccountNil
  701. }
  702. log.Error("TODO")
  703. return nil, errTODO
  704. }
  705. // RollupDeposit is the interface to call the smart contract function
  706. func (c *Client) RollupDeposit(fromIdx int64, loadAmountF common.Float16, tokenID int64) (tx *types.Transaction, err error) {
  707. c.rw.Lock()
  708. defer c.rw.Unlock()
  709. cpy := c.nextBlock().copy()
  710. defer func() { c.revertIfErr(err, cpy) }()
  711. if c.addr == nil {
  712. return nil, eth.ErrAccountNil
  713. }
  714. log.Error("TODO")
  715. return nil, errTODO
  716. }
  717. // RollupCreateAccountDepositFromRelayer is the interface to call the smart contract function
  718. func (c *Client) RollupCreateAccountDepositFromRelayer(accountCreationAuthSig []byte, babyPubKey babyjub.PublicKey, loadAmountF common.Float16) (tx *types.Transaction, err error) {
  719. c.rw.Lock()
  720. defer c.rw.Unlock()
  721. cpy := c.nextBlock().copy()
  722. defer func() { c.revertIfErr(err, cpy) }()
  723. if c.addr == nil {
  724. return nil, eth.ErrAccountNil
  725. }
  726. log.Error("TODO")
  727. return nil, errTODO
  728. }
  729. // RollupCreateAccountDeposit is the interface to call the smart contract function
  730. func (c *Client) RollupCreateAccountDeposit(babyPubKey babyjub.PublicKey, loadAmountF common.Float16, tokenID int64) (tx *types.Transaction, err error) {
  731. c.rw.Lock()
  732. defer c.rw.Unlock()
  733. cpy := c.nextBlock().copy()
  734. defer func() { c.revertIfErr(err, cpy) }()
  735. if c.addr == nil {
  736. return nil, eth.ErrAccountNil
  737. }
  738. log.Error("TODO")
  739. return nil, errTODO
  740. }
  741. // RollupGetTokenAddress is the interface to call the smart contract function
  742. // func (c *Client) RollupGetTokenAddress(tokenID int64) (*ethCommon.Address, error) {
  743. // c.rw.RLock()
  744. // defer c.rw.RUnlock()
  745. //
  746. // log.Error("TODO")
  747. // return nil, errTODO
  748. // }
  749. // RollupGetL1TxFromQueue is the interface to call the smart contract function
  750. // func (c *Client) RollupGetL1TxFromQueue(queue int64, position int64) ([]byte, error) {
  751. // c.rw.RLock()
  752. // defer c.rw.RUnlock()
  753. //
  754. // log.Error("TODO")
  755. // return nil, errTODO
  756. // }
  757. // RollupGetQueue is the interface to call the smart contract function
  758. // func (c *Client) RollupGetQueue(queue int64) ([]byte, error) {
  759. // c.rw.RLock()
  760. // defer c.rw.RUnlock()
  761. //
  762. // log.Error("TODO")
  763. // return nil, errTODO
  764. // }
  765. // RollupUpdateForgeL1L2BatchTimeout is the interface to call the smart contract function
  766. func (c *Client) RollupUpdateForgeL1L2BatchTimeout(newForgeL1Timeout int64) (tx *types.Transaction, err error) {
  767. c.rw.Lock()
  768. defer c.rw.Unlock()
  769. cpy := c.nextBlock().copy()
  770. defer func() { c.revertIfErr(err, cpy) }()
  771. if c.addr == nil {
  772. return nil, eth.ErrAccountNil
  773. }
  774. log.Error("TODO")
  775. return nil, errTODO
  776. }
  777. // RollupUpdateFeeAddToken is the interface to call the smart contract function
  778. func (c *Client) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (tx *types.Transaction, err error) {
  779. c.rw.Lock()
  780. defer c.rw.Unlock()
  781. cpy := c.nextBlock().copy()
  782. defer func() { c.revertIfErr(err, cpy) }()
  783. if c.addr == nil {
  784. return nil, eth.ErrAccountNil
  785. }
  786. log.Error("TODO")
  787. return nil, errTODO
  788. }
  789. // RollupUpdateTokensHEZ is the interface to call the smart contract function
  790. // func (c *Client) RollupUpdateTokensHEZ(newTokenHEZ ethCommon.Address) (tx *types.Transaction, err error) {
  791. // c.rw.Lock()
  792. // defer c.rw.Unlock()
  793. // cpy := c.nextBlock().copy()
  794. // defer func() { c.revertIfErr(err, cpy) }()
  795. //
  796. // log.Error("TODO")
  797. // return nil, errTODO
  798. // }
  799. // RollupUpdateGovernance is the interface to call the smart contract function
  800. // func (c *Client) RollupUpdateGovernance() (*types.Transaction, error) { // TODO (Not defined in Hermez.sol)
  801. // return nil, errTODO
  802. // }
  803. // RollupConstants returns the Constants of the Rollup Smart Contract
  804. func (c *Client) RollupConstants() (*eth.RollupPublicConstants, error) {
  805. c.rw.RLock()
  806. defer c.rw.RUnlock()
  807. log.Error("TODO")
  808. return nil, errTODO
  809. }
  810. // RollupEventsByBlock returns the events in a block that happened in the Rollup Smart Contract
  811. func (c *Client) RollupEventsByBlock(blockNum int64) (*eth.RollupEvents, *ethCommon.Hash, error) {
  812. c.rw.RLock()
  813. defer c.rw.RUnlock()
  814. block, ok := c.blocks[blockNum]
  815. if !ok {
  816. return nil, nil, fmt.Errorf("Block %v doesn't exist", blockNum)
  817. }
  818. return &block.Rollup.Events, &block.Eth.Hash, nil
  819. }
  820. // RollupForgeBatchArgs returns the arguments used in a ForgeBatch call in the Rollup Smart Contract in the given transaction
  821. func (c *Client) RollupForgeBatchArgs(ethTxHash ethCommon.Hash) (*eth.RollupForgeBatchArgs, error) {
  822. c.rw.RLock()
  823. defer c.rw.RUnlock()
  824. forgeBatchArgs, ok := c.forgeBatchArgs[ethTxHash]
  825. if !ok {
  826. return nil, fmt.Errorf("transaction not found")
  827. }
  828. return forgeBatchArgs, nil
  829. }
  830. //
  831. // Auction
  832. //
  833. // AuctionSetSlotDeadline is the interface to call the smart contract function
  834. func (c *Client) AuctionSetSlotDeadline(newDeadline uint8) (tx *types.Transaction, err error) {
  835. c.rw.Lock()
  836. defer c.rw.Unlock()
  837. cpy := c.nextBlock().copy()
  838. defer func() { c.revertIfErr(err, cpy) }()
  839. if c.addr == nil {
  840. return nil, eth.ErrAccountNil
  841. }
  842. log.Error("TODO")
  843. return nil, errTODO
  844. }
  845. // AuctionGetSlotDeadline is the interface to call the smart contract function
  846. func (c *Client) AuctionGetSlotDeadline() (uint8, error) {
  847. c.rw.RLock()
  848. defer c.rw.RUnlock()
  849. log.Error("TODO")
  850. return 0, errTODO
  851. }
  852. // AuctionSetOpenAuctionSlots is the interface to call the smart contract function
  853. func (c *Client) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (tx *types.Transaction, err error) {
  854. c.rw.Lock()
  855. defer c.rw.Unlock()
  856. cpy := c.nextBlock().copy()
  857. defer func() { c.revertIfErr(err, cpy) }()
  858. if c.addr == nil {
  859. return nil, eth.ErrAccountNil
  860. }
  861. log.Error("TODO")
  862. return nil, errTODO
  863. }
  864. // AuctionGetOpenAuctionSlots is the interface to call the smart contract function
  865. func (c *Client) AuctionGetOpenAuctionSlots() (uint16, error) {
  866. c.rw.RLock()
  867. defer c.rw.RUnlock()
  868. log.Error("TODO")
  869. return 0, errTODO
  870. }
  871. // AuctionSetClosedAuctionSlots is the interface to call the smart contract function
  872. func (c *Client) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (tx *types.Transaction, err error) {
  873. c.rw.Lock()
  874. defer c.rw.Unlock()
  875. cpy := c.nextBlock().copy()
  876. defer func() { c.revertIfErr(err, cpy) }()
  877. if c.addr == nil {
  878. return nil, eth.ErrAccountNil
  879. }
  880. log.Error("TODO")
  881. return nil, errTODO
  882. }
  883. // AuctionGetClosedAuctionSlots is the interface to call the smart contract function
  884. func (c *Client) AuctionGetClosedAuctionSlots() (uint16, error) {
  885. c.rw.RLock()
  886. defer c.rw.RUnlock()
  887. log.Error("TODO")
  888. return 0, errTODO
  889. }
  890. // AuctionSetOutbidding is the interface to call the smart contract function
  891. func (c *Client) AuctionSetOutbidding(newOutbidding uint16) (tx *types.Transaction, err error) {
  892. c.rw.Lock()
  893. defer c.rw.Unlock()
  894. cpy := c.nextBlock().copy()
  895. defer func() { c.revertIfErr(err, cpy) }()
  896. if c.addr == nil {
  897. return nil, eth.ErrAccountNil
  898. }
  899. log.Error("TODO")
  900. return nil, errTODO
  901. }
  902. // AuctionGetOutbidding is the interface to call the smart contract function
  903. func (c *Client) AuctionGetOutbidding() (uint16, error) {
  904. c.rw.RLock()
  905. defer c.rw.RUnlock()
  906. log.Error("TODO")
  907. return 0, errTODO
  908. }
  909. // AuctionSetAllocationRatio is the interface to call the smart contract function
  910. func (c *Client) AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (tx *types.Transaction, err error) {
  911. c.rw.Lock()
  912. defer c.rw.Unlock()
  913. cpy := c.nextBlock().copy()
  914. defer func() { c.revertIfErr(err, cpy) }()
  915. if c.addr == nil {
  916. return nil, eth.ErrAccountNil
  917. }
  918. log.Error("TODO")
  919. return nil, errTODO
  920. }
  921. // AuctionGetAllocationRatio is the interface to call the smart contract function
  922. func (c *Client) AuctionGetAllocationRatio() ([3]uint16, error) {
  923. c.rw.RLock()
  924. defer c.rw.RUnlock()
  925. log.Error("TODO")
  926. return [3]uint16{}, errTODO
  927. }
  928. // AuctionSetDonationAddress is the interface to call the smart contract function
  929. func (c *Client) AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (tx *types.Transaction, err error) {
  930. c.rw.Lock()
  931. defer c.rw.Unlock()
  932. cpy := c.nextBlock().copy()
  933. defer func() { c.revertIfErr(err, cpy) }()
  934. if c.addr == nil {
  935. return nil, eth.ErrAccountNil
  936. }
  937. log.Error("TODO")
  938. return nil, errTODO
  939. }
  940. // AuctionGetDonationAddress is the interface to call the smart contract function
  941. func (c *Client) AuctionGetDonationAddress() (*ethCommon.Address, error) {
  942. c.rw.RLock()
  943. defer c.rw.RUnlock()
  944. log.Error("TODO")
  945. return nil, errTODO
  946. }
  947. // AuctionSetBootCoordinator is the interface to call the smart contract function
  948. func (c *Client) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address) (tx *types.Transaction, err error) {
  949. c.rw.Lock()
  950. defer c.rw.Unlock()
  951. cpy := c.nextBlock().copy()
  952. defer func() { c.revertIfErr(err, cpy) }()
  953. if c.addr == nil {
  954. return nil, eth.ErrAccountNil
  955. }
  956. log.Error("TODO")
  957. return nil, errTODO
  958. }
  959. // AuctionGetBootCoordinator is the interface to call the smart contract function
  960. func (c *Client) AuctionGetBootCoordinator() (*ethCommon.Address, error) {
  961. c.rw.RLock()
  962. defer c.rw.RUnlock()
  963. currentBlock := c.currentBlock()
  964. a := currentBlock.Auction
  965. return &a.Vars.BootCoordinator, nil
  966. }
  967. // AuctionChangeDefaultSlotSetBid is the interface to call the smart contract function
  968. func (c *Client) AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (tx *types.Transaction, err error) {
  969. c.rw.Lock()
  970. defer c.rw.Unlock()
  971. cpy := c.nextBlock().copy()
  972. defer func() { c.revertIfErr(err, cpy) }()
  973. if c.addr == nil {
  974. return nil, eth.ErrAccountNil
  975. }
  976. log.Error("TODO")
  977. return nil, errTODO
  978. }
  979. // AuctionSetCoordinator is the interface to call the smart contract function
  980. func (c *Client) AuctionSetCoordinator(forger ethCommon.Address, URL string) (tx *types.Transaction, err error) {
  981. c.rw.Lock()
  982. defer c.rw.Unlock()
  983. cpy := c.nextBlock().copy()
  984. defer func() { c.revertIfErr(err, cpy) }()
  985. if c.addr == nil {
  986. return nil, eth.ErrAccountNil
  987. }
  988. nextBlock := c.nextBlock()
  989. a := nextBlock.Auction
  990. a.State.Coordinators[*c.addr] = &eth.Coordinator{
  991. Forger: forger,
  992. URL: URL,
  993. }
  994. a.Events.SetCoordinator = append(a.Events.SetCoordinator,
  995. eth.AuctionEventSetCoordinator{
  996. BidderAddress: *c.addr,
  997. ForgerAddress: forger,
  998. CoordinatorURL: URL,
  999. })
  1000. type data struct {
  1001. BidderAddress ethCommon.Address
  1002. ForgerAddress ethCommon.Address
  1003. URL string
  1004. }
  1005. return a.addTransaction(newTransaction("registercoordinator", data{*c.addr, forger, URL})), nil
  1006. }
  1007. // AuctionIsRegisteredCoordinator is the interface to call the smart contract function
  1008. func (c *Client) AuctionIsRegisteredCoordinator(forgerAddress ethCommon.Address) (bool, error) {
  1009. c.rw.RLock()
  1010. defer c.rw.RUnlock()
  1011. log.Error("TODO")
  1012. return false, errTODO
  1013. }
  1014. // AuctionUpdateCoordinatorInfo is the interface to call the smart contract function
  1015. func (c *Client) AuctionUpdateCoordinatorInfo(forgerAddress ethCommon.Address, newWithdrawAddress ethCommon.Address, newURL string) (tx *types.Transaction, err error) {
  1016. c.rw.Lock()
  1017. defer c.rw.Unlock()
  1018. cpy := c.nextBlock().copy()
  1019. defer func() { c.revertIfErr(err, cpy) }()
  1020. if c.addr == nil {
  1021. return nil, eth.ErrAccountNil
  1022. }
  1023. log.Error("TODO")
  1024. return nil, errTODO
  1025. }
  1026. // AuctionGetSlotNumber is the interface to call the smart contract function
  1027. func (c *Client) AuctionGetSlotNumber(blockNum int64) (int64, error) {
  1028. c.rw.RLock()
  1029. defer c.rw.RUnlock()
  1030. currentBlock := c.currentBlock()
  1031. a := currentBlock.Auction
  1032. return a.getSlotNumber(blockNum), nil
  1033. }
  1034. // AuctionGetCurrentSlotNumber is the interface to call the smart contract function
  1035. func (c *Client) AuctionGetCurrentSlotNumber() (int64, error) {
  1036. c.rw.RLock()
  1037. defer c.rw.RUnlock()
  1038. log.Error("TODO")
  1039. return 0, errTODO
  1040. }
  1041. // AuctionGetMinBidBySlot is the interface to call the smart contract function
  1042. func (c *Client) AuctionGetMinBidBySlot(slot int64) (*big.Int, error) {
  1043. c.rw.RLock()
  1044. defer c.rw.RUnlock()
  1045. log.Error("TODO")
  1046. return nil, errTODO
  1047. }
  1048. // AuctionGetDefaultSlotSetBid is the interface to call the smart contract function
  1049. func (c *Client) AuctionGetDefaultSlotSetBid(slotSet uint8) (*big.Int, error) {
  1050. c.rw.RLock()
  1051. defer c.rw.RUnlock()
  1052. log.Error("TODO")
  1053. return nil, errTODO
  1054. }
  1055. // AuctionGetSlotSet is the interface to call the smart contract function
  1056. func (c *Client) AuctionGetSlotSet(slot int64) (*big.Int, error) {
  1057. c.rw.RLock()
  1058. defer c.rw.RUnlock()
  1059. log.Error("TODO")
  1060. return nil, errTODO
  1061. }
  1062. // AuctionTokensReceived is the interface to call the smart contract function
  1063. // func (c *Client) AuctionTokensReceived(operator, from, to ethCommon.Address, amount *big.Int, userData, operatorData []byte) error {
  1064. // return errTODO
  1065. // }
  1066. // AuctionBid is the interface to call the smart contract function
  1067. func (c *Client) AuctionBid(slot int64, bidAmount *big.Int) (tx *types.Transaction, err error) {
  1068. c.rw.Lock()
  1069. defer c.rw.Unlock()
  1070. cpy := c.nextBlock().copy()
  1071. defer func() { func() { c.revertIfErr(err, cpy) }() }()
  1072. if c.addr == nil {
  1073. return nil, eth.ErrAccountNil
  1074. }
  1075. nextBlock := c.nextBlock()
  1076. a := nextBlock.Auction
  1077. if slot < a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots) {
  1078. return nil, errBidClosed
  1079. }
  1080. if slot >= a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots)+int64(a.Vars.OpenAuctionSlots) {
  1081. return nil, errBidNotOpen
  1082. }
  1083. minBid, err := a.getMinBidBySlot(slot)
  1084. if err != nil {
  1085. return nil, err
  1086. }
  1087. if bidAmount.Cmp(minBid) == -1 {
  1088. return nil, errBidBelowMin
  1089. }
  1090. if _, ok := a.State.Coordinators[*c.addr]; !ok {
  1091. return nil, errCoordNotReg
  1092. }
  1093. slotState, ok := a.State.Slots[slot]
  1094. if !ok {
  1095. slotState = eth.NewSlotState()
  1096. a.State.Slots[slot] = slotState
  1097. }
  1098. slotState.Bidder = *c.addr
  1099. slotState.BidAmount = bidAmount
  1100. a.Events.NewBid = append(a.Events.NewBid,
  1101. eth.AuctionEventNewBid{Slot: slot, BidAmount: bidAmount, Bidder: *c.addr})
  1102. type data struct {
  1103. Slot int64
  1104. BidAmount *big.Int
  1105. Bidder ethCommon.Address
  1106. }
  1107. return a.addTransaction(newTransaction("bid", data{slot, bidAmount, *c.addr})), nil
  1108. }
  1109. // AuctionMultiBid is the interface to call the smart contract function
  1110. func (c *Client) AuctionMultiBid(startingSlot int64, endingSlot int64, slotSet [6]bool, maxBid, closedMinBid, budget *big.Int) (tx *types.Transaction, err error) {
  1111. c.rw.Lock()
  1112. defer c.rw.Unlock()
  1113. cpy := c.nextBlock().copy()
  1114. defer func() { c.revertIfErr(err, cpy) }()
  1115. if c.addr == nil {
  1116. return nil, eth.ErrAccountNil
  1117. }
  1118. log.Error("TODO")
  1119. return nil, errTODO
  1120. }
  1121. // AuctionCanForge is the interface to call the smart contract function
  1122. func (c *Client) AuctionCanForge(forger ethCommon.Address, blockNum int64) (bool, error) {
  1123. c.rw.RLock()
  1124. defer c.rw.RUnlock()
  1125. currentBlock := c.currentBlock()
  1126. a := currentBlock.Auction
  1127. return a.canForge(forger, blockNum)
  1128. }
  1129. // AuctionForge is the interface to call the smart contract function
  1130. func (c *Client) AuctionForge(forger ethCommon.Address) (tx *types.Transaction, err error) {
  1131. c.rw.Lock()
  1132. defer c.rw.Unlock()
  1133. cpy := c.nextBlock().copy()
  1134. defer func() { c.revertIfErr(err, cpy) }()
  1135. if c.addr == nil {
  1136. return nil, eth.ErrAccountNil
  1137. }
  1138. log.Error("TODO")
  1139. return nil, errTODO
  1140. }
  1141. // AuctionClaimHEZ is the interface to call the smart contract function
  1142. func (c *Client) AuctionClaimHEZ() (tx *types.Transaction, err error) {
  1143. c.rw.Lock()
  1144. defer c.rw.Unlock()
  1145. cpy := c.nextBlock().copy()
  1146. defer func() { c.revertIfErr(err, cpy) }()
  1147. if c.addr == nil {
  1148. return nil, eth.ErrAccountNil
  1149. }
  1150. log.Error("TODO")
  1151. return nil, errTODO
  1152. }
  1153. // AuctionGetClaimableHEZ is the interface to call the smart contract function
  1154. func (c *Client) AuctionGetClaimableHEZ(bidder ethCommon.Address) (*big.Int, error) {
  1155. c.rw.RLock()
  1156. defer c.rw.RUnlock()
  1157. log.Error("TODO")
  1158. return nil, errTODO
  1159. }
  1160. // AuctionConstants returns the Constants of the Auction Smart Contract
  1161. func (c *Client) AuctionConstants() (*eth.AuctionConstants, error) {
  1162. c.rw.RLock()
  1163. defer c.rw.RUnlock()
  1164. return c.auctionConstants, nil
  1165. }
  1166. // AuctionEventsByBlock returns the events in a block that happened in the Auction Smart Contract
  1167. func (c *Client) AuctionEventsByBlock(blockNum int64) (*eth.AuctionEvents, *ethCommon.Hash, error) {
  1168. c.rw.RLock()
  1169. defer c.rw.RUnlock()
  1170. block, ok := c.blocks[blockNum]
  1171. if !ok {
  1172. return nil, nil, fmt.Errorf("Block %v doesn't exist", blockNum)
  1173. }
  1174. return &block.Auction.Events, &block.Eth.Hash, nil
  1175. }