github.com/klaytn/klaytn@v1.12.1/node/sc/bridge_test.go (about)

     1  // Copyright 2019 The klaytn Authors
     2  // This file is part of the klaytn library.
     3  //
     4  // The klaytn library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The klaytn library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package sc
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"log"
    23  	"math/big"
    24  	"strconv"
    25  	"testing"
    26  	"time"
    27  
    28  	"github.com/klaytn/klaytn/accounts/abi/bind"
    29  	"github.com/klaytn/klaytn/accounts/abi/bind/backends"
    30  	"github.com/klaytn/klaytn/blockchain"
    31  	"github.com/klaytn/klaytn/blockchain/types"
    32  	"github.com/klaytn/klaytn/common"
    33  	"github.com/klaytn/klaytn/contracts/bridge"
    34  	"github.com/klaytn/klaytn/contracts/extbridge"
    35  	sctoken "github.com/klaytn/klaytn/contracts/sc_erc20"
    36  	scnft "github.com/klaytn/klaytn/contracts/sc_erc721"
    37  	"github.com/klaytn/klaytn/crypto"
    38  	"github.com/klaytn/klaytn/params"
    39  	"github.com/stretchr/testify/assert"
    40  )
    41  
    42  const (
    43  	timeOut                 = 3 * time.Second // timeout of context and event loop for simulated backend.
    44  	DefaultBridgeTxGasLimit = uint64(10000000)
    45  )
    46  
    47  // WaitMined waits the tx receipt until the timeout.
    48  func WaitMined(tx *types.Transaction, backend bind.DeployBackend, t *testing.T) error {
    49  	timeoutContext, cancelTimeout := context.WithTimeout(context.Background(), timeOut)
    50  	defer cancelTimeout()
    51  
    52  	receipt, err := bind.WaitMined(timeoutContext, backend, tx)
    53  	if err != nil {
    54  		t.Fatal("Failed to WaitMined.", "err", err, "txHash", tx.Hash().String(), "status", receipt.Status)
    55  		return err
    56  	}
    57  
    58  	if receipt == nil {
    59  		return errors.New("receipt not found")
    60  	}
    61  
    62  	if receipt.Status != types.ReceiptStatusSuccessful {
    63  		t.Log("receipt", "status", receipt.Status)
    64  		return errors.New("not successful receipt")
    65  	}
    66  	return nil
    67  }
    68  
    69  // TransferSignedTx sends the transaction to transfer KLAY from auth to `to` and waits the execution of the transaction.
    70  func TransferSignedTx(auth *bind.TransactOpts, backend *backends.SimulatedBackend, to common.Address, value *big.Int, t *testing.T) (common.Hash, *big.Int, error) {
    71  	ctx := context.Background()
    72  
    73  	nonce, err := backend.NonceAt(ctx, auth.From, nil)
    74  	assert.Equal(t, err, nil)
    75  
    76  	chainID, err := backend.ChainID(ctx)
    77  	assert.Equal(t, err, nil)
    78  
    79  	gasPrice, err := backend.SuggestGasPrice(ctx)
    80  	assert.Equal(t, err, nil)
    81  
    82  	tx := types.NewTransaction(
    83  		nonce,
    84  		to,
    85  		value,
    86  		DefaultBridgeTxGasLimit,
    87  		gasPrice,
    88  		nil)
    89  
    90  	signedTx, err := auth.Signer(types.LatestSignerForChainID(chainID), auth.From, tx)
    91  	assert.Equal(t, err, nil)
    92  
    93  	fee := big.NewInt(0)
    94  
    95  	err = backend.SendTransaction(ctx, signedTx)
    96  	assert.Equal(t, err, nil)
    97  
    98  	backend.Commit()
    99  
   100  	ctx, cancel := context.WithTimeout(context.Background(), timeOut)
   101  	defer cancel()
   102  	receipt, err := bind.WaitMined(ctx, backend, signedTx)
   103  	if err != nil {
   104  		log.Fatalf("WaitMined time out %v", err)
   105  	}
   106  
   107  	fee.Mul(big.NewInt(int64(receipt.GasUsed)), gasPrice)
   108  
   109  	return tx.Hash(), fee, nil
   110  }
   111  
   112  // RequestKLAYTransfer sends a requestValueTransfer transaction to the bridge contract.
   113  func RequestKLAYTransfer(b *bridge.Bridge, auth *bind.TransactOpts, to common.Address, value uint64, t *testing.T) {
   114  	_, err := b.RequestKLAYTransfer(&bind.TransactOpts{From: auth.From, Signer: auth.Signer, GasLimit: DefaultBridgeTxGasLimit, Value: new(big.Int).SetUint64(value)}, to, new(big.Int).SetUint64(value), nil)
   115  	if err != nil {
   116  		t.Fatalf("fail to RequestKLAYTransfer %v", err)
   117  	}
   118  }
   119  
   120  // SendHandleKLAYTransfer send a handleValueTransfer transaction to the bridge contract.
   121  func SendHandleKLAYTransfer(b *bridge.Bridge, auth *bind.TransactOpts, to common.Address, value uint64, nonce uint64, blockNum uint64, t *testing.T) *types.Transaction {
   122  	tx, err := b.HandleKLAYTransfer(&bind.TransactOpts{From: auth.From, Signer: auth.Signer, GasLimit: DefaultBridgeTxGasLimit}, common.Hash{10}, common.Address{0}, to, big.NewInt(int64(value)), nonce, blockNum, nil)
   123  	if err != nil {
   124  		t.Fatalf("fail to SendHandleKLAYTransfer %v", err)
   125  		return nil
   126  	}
   127  	return tx
   128  }
   129  
   130  // TestBridgeDeployWithKLAY checks to the state/contract balance of the bridge deployed.
   131  func TestBridgeDeployWithKLAY(t *testing.T) {
   132  	bridgeAccountKey, _ := crypto.GenerateKey()
   133  	bridgeAccount := bind.NewKeyedTransactor(bridgeAccountKey)
   134  
   135  	alloc := blockchain.GenesisAlloc{bridgeAccount.From: {Balance: big.NewInt(params.KLAY)}}
   136  	backend := backends.NewSimulatedBackend(alloc)
   137  	defer backend.Close()
   138  
   139  	chargeAmount := big.NewInt(10000000)
   140  	bridgeAccount.Value = chargeAmount
   141  	bridgeAddress, tx, _, err := bridge.DeployBridge(bridgeAccount, backend, false)
   142  	if err != nil {
   143  		t.Fatalf("fail to DeployBridge %v", err)
   144  	}
   145  	backend.Commit()
   146  	WaitMined(tx, backend, t)
   147  
   148  	balanceContract, err := backend.BalanceAt(nil, bridgeAddress, nil)
   149  	if err != nil {
   150  		t.Fatalf("fail to GetKLAY %v", err)
   151  	}
   152  
   153  	balanceState, err := backend.BalanceAt(context.Background(), bridgeAddress, nil)
   154  	if err != nil {
   155  		t.Fatal("failed to BalanceAt")
   156  	}
   157  
   158  	assert.Equal(t, chargeAmount, balanceState)
   159  	assert.Equal(t, chargeAmount, balanceContract)
   160  }
   161  
   162  // TestBridgeRequestValueTransferNonce checks the bridge emit events with serialized nonce.
   163  func TestBridgeRequestValueTransferNonce(t *testing.T) {
   164  	bridgeAccountKey, _ := crypto.GenerateKey()
   165  	bridgeAccount := bind.NewKeyedTransactor(bridgeAccountKey)
   166  
   167  	testAccKey, _ := crypto.GenerateKey()
   168  	testAcc := bind.NewKeyedTransactor(testAccKey)
   169  
   170  	alloc := blockchain.GenesisAlloc{bridgeAccount.From: {Balance: big.NewInt(params.KLAY)}}
   171  	backend := backends.NewSimulatedBackend(alloc)
   172  	defer backend.Close()
   173  
   174  	chargeAmount := big.NewInt(10000000)
   175  	bridgeAccount.Value = chargeAmount
   176  	addr, tx, b, err := bridge.DeployBridge(bridgeAccount, backend, false)
   177  	if err != nil {
   178  		t.Fatalf("fail to DeployBridge %v", err)
   179  	}
   180  	backend.Commit()
   181  	WaitMined(tx, backend, t)
   182  	t.Log("1. Bridge is deployed.", "addr=", addr.String(), "txHash=", tx.Hash().String())
   183  
   184  	requestValueTransferEventCh := make(chan *bridge.BridgeRequestValueTransfer, 100)
   185  	requestSub, err := b.WatchRequestValueTransfer(nil, requestValueTransferEventCh, nil, nil, nil)
   186  	defer requestSub.Unsubscribe()
   187  	if err != nil {
   188  		t.Fatalf("fail to WatchHandleValueTransfer %v", err)
   189  	}
   190  	t.Log("2. Bridge is subscribed.")
   191  
   192  	RequestKLAYTransfer(b, bridgeAccount, testAcc.From, 1, t)
   193  	backend.Commit()
   194  
   195  	expectedNonce := uint64(0)
   196  
   197  loop:
   198  	for {
   199  		select {
   200  		case ev := <-requestValueTransferEventCh:
   201  			assert.Equal(t, expectedNonce, ev.RequestNonce)
   202  
   203  			if expectedNonce == 1000 {
   204  				return
   205  			}
   206  			expectedNonce++
   207  
   208  			// TODO-Klaytn added more request token/NFT transfer cases,
   209  			RequestKLAYTransfer(b, bridgeAccount, testAcc.From, 1, t)
   210  			backend.Commit()
   211  
   212  		case err := <-requestSub.Err():
   213  			t.Log("Contract Event Loop Running Stop by requestSub.Err()", "err", err)
   214  			break loop
   215  
   216  		case <-time.After(timeOut):
   217  			t.Log("Contract Event Loop Running Stop by timeout")
   218  			break loop
   219  		}
   220  	}
   221  
   222  	t.Fatal("fail to check monotone increasing nonce", "lastNonce", expectedNonce)
   223  }
   224  
   225  // TestBridgeHandleValueTransferNonceAndBlockNumber checks the following:
   226  // - the bridge allows the handle value transfer with an arbitrary nonce.
   227  // - the bridge keeps lower handle nonce for the recovery.
   228  // - the bridge correctly stores and returns the block number.
   229  func TestBridgeHandleValueTransferNonceAndBlockNumber(t *testing.T) {
   230  	bridgeAccountKey, _ := crypto.GenerateKey()
   231  	bridgeAccount := bind.NewKeyedTransactor(bridgeAccountKey)
   232  
   233  	testAccKey, _ := crypto.GenerateKey()
   234  	testAcc := bind.NewKeyedTransactor(testAccKey)
   235  
   236  	alloc := blockchain.GenesisAlloc{bridgeAccount.From: {Balance: big.NewInt(params.KLAY)}}
   237  	backend := backends.NewSimulatedBackend(alloc)
   238  	defer backend.Close()
   239  
   240  	chargeAmount := big.NewInt(10000000)
   241  	bridgeAccount.Value = chargeAmount
   242  	bridgeAddress, tx, b, err := bridge.DeployBridge(bridgeAccount, backend, false)
   243  	if err != nil {
   244  		t.Fatalf("fail to DeployBridge %v", err)
   245  	}
   246  	backend.Commit()
   247  	WaitMined(tx, backend, t)
   248  	t.Log("1. Bridge is deployed.", "bridgeAddress=", bridgeAddress.String(), "txHash=", tx.Hash().String())
   249  
   250  	tx, err = b.RegisterOperator(&bind.TransactOpts{From: bridgeAccount.From, Signer: bridgeAccount.Signer, GasLimit: DefaultBridgeTxGasLimit}, bridgeAccount.From)
   251  	assert.NoError(t, err)
   252  	backend.Commit()
   253  	WaitMined(tx, backend, t)
   254  
   255  	handleValueTransferEventCh := make(chan *bridge.BridgeHandleValueTransfer, 100)
   256  	handleSub, err := b.WatchHandleValueTransfer(nil, handleValueTransferEventCh, nil, nil, nil)
   257  	assert.NoError(t, err)
   258  	defer handleSub.Unsubscribe()
   259  	if err != nil {
   260  		t.Fatalf("fail to DepositKLAY %v", err)
   261  	}
   262  	t.Log("2. Bridge is subscribed.")
   263  
   264  	nonceOffset := uint64(17)
   265  	sentNonce := nonceOffset
   266  	testCount := uint64(1000)
   267  	transferAmount := uint64(100)
   268  	sentBlockNumber := uint64(100000)
   269  	tx = SendHandleKLAYTransfer(b, bridgeAccount, testAcc.From, transferAmount, sentNonce, sentBlockNumber, t)
   270  	backend.Commit()
   271  
   272  	timeoutContext, cancelTimeout := context.WithTimeout(context.Background(), timeOut)
   273  	defer cancelTimeout()
   274  
   275  	receipt, err := bind.WaitMined(timeoutContext, backend, tx)
   276  	if err != nil {
   277  		t.Fatal("Failed to WaitMined.", "err", err, "txHash", tx.Hash().String(), "status", receipt.Status)
   278  	}
   279  
   280  loop:
   281  	for {
   282  		select {
   283  		case ev := <-handleValueTransferEventCh:
   284  			assert.Equal(t, sentNonce, ev.HandleNonce)
   285  
   286  			if sentNonce == testCount {
   287  				bal, err := backend.BalanceAt(context.Background(), testAcc.From, nil)
   288  				assert.NoError(t, err)
   289  				assert.Equal(t, bal, big.NewInt(int64(transferAmount*(testCount-nonceOffset+1))))
   290  
   291  				lowerHandleNonce, err := b.LowerHandleNonce(nil)
   292  				assert.NoError(t, err)
   293  				assert.Equal(t, lowerHandleNonce, uint64(0))
   294  				return
   295  			}
   296  			sentNonce++
   297  			sentBlockNumber++
   298  
   299  			SendHandleKLAYTransfer(b, bridgeAccount, testAcc.From, transferAmount, sentNonce, sentBlockNumber, t)
   300  			backend.Commit()
   301  
   302  			resultBlockNumber, err := b.RecoveryBlockNumber(nil)
   303  			assert.NoError(t, err)
   304  
   305  			resultHandleNonce, err := b.UpperHandleNonce(nil)
   306  			assert.NoError(t, err)
   307  
   308  			assert.Equal(t, sentNonce, resultHandleNonce)
   309  			assert.Equal(t, uint64(1), resultBlockNumber)
   310  
   311  		case err := <-handleSub.Err():
   312  			t.Log("Contract Event Loop Running Stop by handleSub.Err()", "err", err)
   313  			break loop
   314  
   315  		case <-time.After(timeOut):
   316  			t.Log("Contract Event Loop Running Stop by timeout")
   317  			break loop
   318  		}
   319  	}
   320  
   321  	t.Fatal("fail to check monotone increasing nonce", "lastNonce", sentNonce)
   322  }
   323  
   324  // TestBridgePublicVariables checks the results of the public variables.
   325  func TestBridgePublicVariables(t *testing.T) {
   326  	bridgeAccountKey, _ := crypto.GenerateKey()
   327  	bridgeAccount := bind.NewKeyedTransactor(bridgeAccountKey)
   328  
   329  	alloc := blockchain.GenesisAlloc{bridgeAccount.From: {Balance: big.NewInt(params.KLAY)}}
   330  	backend := backends.NewSimulatedBackend(alloc)
   331  	defer backend.Close()
   332  
   333  	chargeAmount := big.NewInt(10000000)
   334  	bridgeAccount.Value = chargeAmount
   335  	bridgeAddress, tx, b, err := bridge.DeployBridge(bridgeAccount, backend, false)
   336  	assert.NoError(t, err)
   337  	backend.Commit()
   338  	assert.Nil(t, WaitMined(tx, backend, t))
   339  
   340  	balanceContract, err := backend.BalanceAt(nil, bridgeAddress, nil)
   341  	assert.NoError(t, err)
   342  	assert.Equal(t, chargeAmount, balanceContract)
   343  
   344  	ctx := context.Background()
   345  	nonce, err := backend.NonceAt(ctx, bridgeAccount.From, nil)
   346  	gasPrice, err := backend.SuggestGasPrice(ctx)
   347  	opts := bind.MakeTransactOpts(bridgeAccountKey, big.NewInt(int64(nonce)), DefaultBridgeTxGasLimit, gasPrice)
   348  
   349  	tx, err = b.SetCounterPartBridge(opts, common.Address{2})
   350  	assert.NoError(t, err)
   351  	backend.Commit()
   352  	assert.Nil(t, WaitMined(tx, backend, t))
   353  
   354  	version, err := b.VERSION(nil)
   355  	assert.Equal(t, uint64(0x1), version)
   356  
   357  	allowedTokens, err := b.RegisteredTokens(nil, common.Address{1})
   358  	assert.Equal(t, common.Address{0}, allowedTokens)
   359  
   360  	counterpartBridge, err := b.CounterpartBridge(nil)
   361  	assert.Equal(t, common.Address{2}, counterpartBridge)
   362  
   363  	hnonce, err := b.LowerHandleNonce(nil)
   364  	assert.Equal(t, uint64(0), hnonce)
   365  
   366  	owner, err := b.IsOwner(&bind.CallOpts{From: bridgeAccount.From})
   367  	assert.Equal(t, true, owner)
   368  
   369  	notOwner, err := b.IsOwner(&bind.CallOpts{From: common.Address{1}})
   370  	assert.Equal(t, false, notOwner)
   371  
   372  	isRunning, err := b.IsRunning(nil)
   373  	assert.Equal(t, true, isRunning)
   374  
   375  	lastBN, err := b.RecoveryBlockNumber(nil)
   376  	assert.Equal(t, uint64(0x1), lastBN)
   377  
   378  	bridgeOwner, err := b.Owner(nil)
   379  	assert.Equal(t, bridgeAccount.From, bridgeOwner)
   380  
   381  	rnonce, err := b.RequestNonce(nil)
   382  	assert.Equal(t, uint64(0), rnonce)
   383  }
   384  
   385  // TestExtendedBridgeAndCallbackERC20 checks the following:
   386  // - the extBridge can call a callback contract method from ERC20 value transfer.
   387  func TestExtendedBridgeAndCallbackERC20(t *testing.T) {
   388  	bridgeAccountKey, _ := crypto.GenerateKey()
   389  	bridgeAccount := bind.NewKeyedTransactor(bridgeAccountKey)
   390  
   391  	aliceKey, _ := crypto.GenerateKey()
   392  	aliceAcc := bind.NewKeyedTransactor(aliceKey)
   393  	aliceAcc.GasLimit = DefaultBridgeTxGasLimit
   394  
   395  	bobKey, _ := crypto.GenerateKey()
   396  	bobAcc := bind.NewKeyedTransactor(bobKey)
   397  
   398  	alloc := blockchain.GenesisAlloc{bridgeAccount.From: {Balance: big.NewInt(params.KLAY)}}
   399  	backend := backends.NewSimulatedBackend(alloc)
   400  	defer backend.Close()
   401  
   402  	// Deploy extBridge
   403  	bridgeAddr, tx, eb, err := extbridge.DeployExtBridge(bridgeAccount, backend, true)
   404  	assert.NoError(t, err)
   405  	backend.Commit()
   406  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   407  
   408  	// Deploy token
   409  	erc20Addr, tx, erc20, err := sctoken.DeployServiceChainToken(bridgeAccount, backend, bridgeAddr)
   410  	assert.NoError(t, err)
   411  	backend.Commit()
   412  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   413  
   414  	// Register token
   415  	tx, err = eb.RegisterToken(bridgeAccount, erc20Addr, erc20Addr)
   416  	assert.NoError(t, err)
   417  	backend.Commit()
   418  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   419  
   420  	// Charge token to Alice
   421  	testToken := big.NewInt(100000)
   422  	tx, err = erc20.Transfer(bridgeAccount, aliceAcc.From, testToken)
   423  	assert.NoError(t, err)
   424  	backend.Commit()
   425  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   426  
   427  	// Give minter role to bridge contract
   428  	tx, err = erc20.AddMinter(bridgeAccount, bridgeAddr)
   429  	assert.NoError(t, err)
   430  	backend.Commit()
   431  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   432  
   433  	// Deploy callback contract
   434  	callbackAddr, tx, cb, err := extbridge.DeployCallback(bridgeAccount, backend)
   435  	assert.NoError(t, err)
   436  	backend.Commit()
   437  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   438  
   439  	// Set callback address to ExtBridge contract
   440  	tx, err = eb.SetCallback(bridgeAccount, callbackAddr)
   441  	assert.NoError(t, err)
   442  	backend.Commit()
   443  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   444  
   445  	// Subscribe callback contract event
   446  	registerOfferEventCh := make(chan *extbridge.CallbackRegisteredOffer, 10)
   447  	registerOfferEventSub, err := cb.WatchRegisteredOffer(nil, registerOfferEventCh)
   448  	assert.NoError(t, err)
   449  	defer registerOfferEventSub.Unsubscribe()
   450  
   451  	// Subscribe bridge contract events
   452  	b, err := bridge.NewBridge(bridgeAddr, backend) // create base bridge contract object, not extBridge object
   453  	assert.NoError(t, err)
   454  
   455  	requestValueTransferEventCh := make(chan *bridge.BridgeRequestValueTransfer, 10)
   456  	requestSub, err := b.WatchRequestValueTransfer(nil, requestValueTransferEventCh, nil, nil, nil)
   457  	assert.NoError(t, err)
   458  	defer requestSub.Unsubscribe()
   459  
   460  	handleValueTransferEventCh := make(chan *bridge.BridgeHandleValueTransfer, 10)
   461  	handleSub, err := b.WatchHandleValueTransfer(nil, handleValueTransferEventCh, nil, nil, nil)
   462  	assert.NoError(t, err)
   463  	defer handleSub.Unsubscribe()
   464  
   465  	// Approve / RequestSellERC20
   466  	rNonce := uint64(0)
   467  	amount := big.NewInt(1000)
   468  	offerPrice := big.NewInt(1006)
   469  
   470  	tx, err = erc20.Approve(aliceAcc, bridgeAddr, amount)
   471  	assert.NoError(t, err)
   472  	backend.Commit()
   473  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   474  
   475  	// Fail case
   476  	tx, err = eb.RequestERC20Transfer(aliceAcc, erc20Addr, bobAcc.From, amount, common.Big0, nil)
   477  	assert.NoError(t, err)
   478  	backend.Commit()
   479  	assert.Error(t, bind.CheckWaitMined(backend, tx))
   480  
   481  	// Success case
   482  	tx, err = eb.RequestSellERC20(aliceAcc, erc20Addr, bobAcc.From, amount, common.Big0, offerPrice)
   483  	assert.NoError(t, err)
   484  	backend.Commit()
   485  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   486  
   487  	// Check request request event
   488  	select {
   489  	case ev := <-requestValueTransferEventCh:
   490  		assert.Equal(t, amount.String(), ev.ValueOrTokenId.String())
   491  		assert.Equal(t, rNonce, ev.RequestNonce)
   492  		assert.Equal(t, erc20Addr, ev.TokenAddress)
   493  		assert.Equal(t, ERC20, ev.TokenType)
   494  		assert.Equal(t, bobAcc.From, ev.To)
   495  
   496  		// HandleERC20Transfer
   497  		tx, err = b.HandleERC20Transfer(bridgeAccount, ev.Raw.TxHash, ev.From, ev.To, ev.TokenAddress, ev.ValueOrTokenId, ev.RequestNonce, ev.Raw.BlockNumber, ev.ExtraData)
   498  		assert.NoError(t, err)
   499  		backend.Commit()
   500  		assert.Nil(t, bind.CheckWaitMined(backend, tx))
   501  
   502  	case <-time.After(time.Second):
   503  		t.Fatalf("requestValueTransferEvent was not found.")
   504  	}
   505  
   506  	// Check handle request event
   507  	select {
   508  	case ev := <-handleValueTransferEventCh:
   509  		assert.Equal(t, amount.String(), ev.ValueOrTokenId.String())
   510  		assert.Equal(t, rNonce, ev.HandleNonce)
   511  		assert.Equal(t, erc20Addr, ev.TokenAddress)
   512  		assert.Equal(t, ERC20, ev.TokenType)
   513  		assert.Equal(t, callbackAddr, ev.To)
   514  
   515  	case <-time.After(time.Second):
   516  		t.Fatalf("handleValueTransferEvent was not found.")
   517  	}
   518  
   519  	// Check Callback event
   520  	select {
   521  	case ev := <-registerOfferEventCh:
   522  		assert.Equal(t, amount.String(), ev.ValueOrID.String())
   523  		assert.Equal(t, offerPrice.String(), ev.Price.String())
   524  		assert.Equal(t, erc20Addr, ev.TokenAddress)
   525  
   526  	case <-time.After(time.Second):
   527  		t.Fatalf("registerOfferEvent was not found.")
   528  	}
   529  }
   530  
   531  // TestExtendedBridgeAndCallbackERC721 checks the following:
   532  // - the extBridge can call a callback contract method from ERC721 value transfer.
   533  func TestExtendedBridgeAndCallbackERC721(t *testing.T) {
   534  	bridgeAccountKey, _ := crypto.GenerateKey()
   535  	bridgeAccount := bind.NewKeyedTransactor(bridgeAccountKey)
   536  
   537  	aliceKey, _ := crypto.GenerateKey()
   538  	aliceAcc := bind.NewKeyedTransactor(aliceKey)
   539  	aliceAcc.GasLimit = DefaultBridgeTxGasLimit
   540  
   541  	bobKey, _ := crypto.GenerateKey()
   542  	bobAcc := bind.NewKeyedTransactor(bobKey)
   543  
   544  	alloc := blockchain.GenesisAlloc{bridgeAccount.From: {Balance: big.NewInt(params.KLAY)}}
   545  	backend := backends.NewSimulatedBackend(alloc)
   546  	defer backend.Close()
   547  
   548  	// Deploy extBridge
   549  	bridgeAddr, tx, eb, err := extbridge.DeployExtBridge(bridgeAccount, backend, true)
   550  	assert.NoError(t, err)
   551  	backend.Commit()
   552  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   553  
   554  	// Deploy token
   555  	erc721Addr, tx, erc721, err := scnft.DeployServiceChainNFT(bridgeAccount, backend, bridgeAddr)
   556  	assert.NoError(t, err)
   557  	backend.Commit()
   558  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   559  
   560  	// Register token
   561  	tx, err = eb.RegisterToken(bridgeAccount, erc721Addr, erc721Addr)
   562  	assert.NoError(t, err)
   563  	backend.Commit()
   564  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   565  
   566  	// Charge token to Alice
   567  	testToken := big.NewInt(100000)
   568  	tx, err = erc721.MintWithTokenURI(bridgeAccount, aliceAcc.From, testToken, "")
   569  	assert.NoError(t, err)
   570  	backend.Commit()
   571  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   572  
   573  	// Give minter role to bridge contract
   574  	tx, err = erc721.AddMinter(bridgeAccount, bridgeAddr)
   575  	assert.NoError(t, err)
   576  	backend.Commit()
   577  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   578  
   579  	// Deploy callback contract
   580  	callbackAddr, tx, cb, err := extbridge.DeployCallback(bridgeAccount, backend)
   581  	assert.NoError(t, err)
   582  	backend.Commit()
   583  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   584  
   585  	// Set callback address to ExtBridge contract
   586  	tx, err = eb.SetCallback(bridgeAccount, callbackAddr)
   587  	assert.NoError(t, err)
   588  	backend.Commit()
   589  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   590  
   591  	// Subscribe callback contract event
   592  	registerOfferEventCh := make(chan *extbridge.CallbackRegisteredOffer, 10)
   593  	registerOfferEventSub, err := cb.WatchRegisteredOffer(nil, registerOfferEventCh)
   594  	assert.NoError(t, err)
   595  	defer registerOfferEventSub.Unsubscribe()
   596  
   597  	// Subscribe bridge contract events
   598  	b, err := bridge.NewBridge(bridgeAddr, backend) // create base bridge contract object, not extBridge object
   599  	assert.NoError(t, err)
   600  
   601  	requestValueTransferEventCh := make(chan *bridge.BridgeRequestValueTransfer, 10)
   602  	requestSub, err := b.WatchRequestValueTransfer(nil, requestValueTransferEventCh, nil, nil, nil)
   603  	assert.NoError(t, err)
   604  	defer requestSub.Unsubscribe()
   605  	requestValueTransferEncodedEventCh := make(chan *bridge.BridgeRequestValueTransferEncoded, 10)
   606  	requestEncodedEvSub, err := b.WatchRequestValueTransferEncoded(nil, requestValueTransferEncodedEventCh, nil, nil, nil)
   607  	assert.NoError(t, err)
   608  	defer requestEncodedEvSub.Unsubscribe()
   609  
   610  	handleValueTransferEventCh := make(chan *bridge.BridgeHandleValueTransfer, 10)
   611  	handleSub, err := b.WatchHandleValueTransfer(nil, handleValueTransferEventCh, nil, nil, nil)
   612  	assert.NoError(t, err)
   613  	defer handleSub.Unsubscribe()
   614  
   615  	// Approve / RequestSellERC721
   616  	rNonce := uint64(0)
   617  	offerPrice := big.NewInt(1006)
   618  
   619  	tx, err = erc721.Approve(aliceAcc, bridgeAddr, testToken)
   620  	assert.NoError(t, err)
   621  	backend.Commit()
   622  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   623  
   624  	// Fail case
   625  	tx, err = eb.RequestERC721Transfer(aliceAcc, erc721Addr, bobAcc.From, testToken, nil)
   626  	assert.NoError(t, err)
   627  	backend.Commit()
   628  	assert.Error(t, bind.CheckWaitMined(backend, tx))
   629  
   630  	// Success case
   631  	tx, err = eb.RequestSellERC721(aliceAcc, erc721Addr, bobAcc.From, testToken, offerPrice)
   632  	assert.NoError(t, err)
   633  	backend.Commit()
   634  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   635  
   636  	// Check request request event
   637  	select {
   638  	case ev := <-requestValueTransferEventCh:
   639  		assert.Equal(t, testToken.String(), ev.ValueOrTokenId.String())
   640  		assert.Equal(t, rNonce, ev.RequestNonce)
   641  		assert.Equal(t, erc721Addr, ev.TokenAddress)
   642  		assert.Equal(t, ERC721, ev.TokenType)
   643  		assert.Equal(t, bobAcc.From, ev.To)
   644  
   645  		// HandleERC721Transfer
   646  		tx, err = b.HandleERC721Transfer(bridgeAccount, ev.Raw.TxHash, ev.From, ev.To, ev.TokenAddress, ev.ValueOrTokenId, ev.RequestNonce, ev.Raw.BlockNumber, "", ev.ExtraData)
   647  		assert.NoError(t, err)
   648  		backend.Commit()
   649  		assert.Nil(t, bind.CheckWaitMined(backend, tx))
   650  
   651  	case ev := <-requestValueTransferEncodedEventCh:
   652  		assert.Equal(t, testToken.String(), ev.ValueOrTokenId.String())
   653  		assert.Equal(t, rNonce, ev.RequestNonce)
   654  		assert.Equal(t, erc721Addr, ev.TokenAddress)
   655  		assert.Equal(t, ERC721, ev.TokenType)
   656  		assert.Equal(t, bobAcc.From, ev.To)
   657  
   658  		// HandleERC721Transfer
   659  		uri := GetURI(RequestValueTransferEncodedEvent{ev})
   660  		tx, err = b.HandleERC721Transfer(bridgeAccount, ev.Raw.TxHash, ev.From, ev.To, ev.TokenAddress, ev.ValueOrTokenId, ev.RequestNonce, ev.Raw.BlockNumber, uri, ev.ExtraData)
   661  		assert.NoError(t, err)
   662  		backend.Commit()
   663  		assert.Nil(t, bind.CheckWaitMined(backend, tx))
   664  	case <-time.After(time.Second):
   665  		t.Fatalf("requestValueTransferEvent was not found.")
   666  	}
   667  
   668  	// Check handle request event
   669  	select {
   670  	case ev := <-handleValueTransferEventCh:
   671  		assert.Equal(t, testToken.String(), ev.ValueOrTokenId.String())
   672  		assert.Equal(t, rNonce, ev.HandleNonce)
   673  		assert.Equal(t, erc721Addr, ev.TokenAddress)
   674  		assert.Equal(t, ERC721, ev.TokenType)
   675  		assert.Equal(t, callbackAddr, ev.To)
   676  
   677  	case <-time.After(time.Second):
   678  		t.Fatalf("handleValueTransferEvent was not found.")
   679  	}
   680  
   681  	// Check Callback event
   682  	select {
   683  	case ev := <-registerOfferEventCh:
   684  		assert.Equal(t, testToken.String(), ev.ValueOrID.String())
   685  		assert.Equal(t, offerPrice.String(), ev.Price.String())
   686  		assert.Equal(t, erc721Addr, ev.TokenAddress)
   687  
   688  	case <-time.After(time.Second):
   689  		t.Fatalf("registerOfferEvent was not found.")
   690  	}
   691  }
   692  
   693  type bridgeTokenTestENV struct {
   694  	backend    *backends.SimulatedBackend
   695  	operator   *bind.TransactOpts
   696  	tester     *bind.TransactOpts
   697  	bridge     *bridge.Bridge
   698  	erc20      *sctoken.ServiceChainToken
   699  	erc721     *scnft.ServiceChainNFT
   700  	erc20Addr  common.Address
   701  	erc721Addr common.Address
   702  }
   703  
   704  func generateBridgeTokenTestEnv(t *testing.T) *bridgeTokenTestENV {
   705  	key, _ := crypto.GenerateKey()
   706  	operator := bind.NewKeyedTransactor(key)
   707  	operator.GasLimit = DefaultBridgeTxGasLimit
   708  
   709  	testKey, _ := crypto.GenerateKey()
   710  	tester := bind.NewKeyedTransactor(testKey)
   711  	tester.GasLimit = DefaultBridgeTxGasLimit
   712  
   713  	alloc := blockchain.GenesisAlloc{operator.From: {Balance: big.NewInt(params.KLAY)}, tester.From: {Balance: big.NewInt(params.KLAY)}}
   714  	backend := backends.NewSimulatedBackend(alloc)
   715  
   716  	// Deploy Bridge
   717  	bridgeAddr, tx, b, err := bridge.DeployBridge(operator, backend, true)
   718  	assert.NoError(t, err)
   719  	backend.Commit()
   720  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   721  
   722  	// Deploy ERC20
   723  	erc20Addr, tx, erc20, err := sctoken.DeployServiceChainToken(operator, backend, bridgeAddr)
   724  	assert.NoError(t, err)
   725  	backend.Commit()
   726  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   727  
   728  	// Register ERC20
   729  	tx, err = b.RegisterToken(operator, erc20Addr, erc20Addr)
   730  	assert.NoError(t, err)
   731  	backend.Commit()
   732  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   733  
   734  	// Charge token to tester
   735  	tx, err = erc20.Transfer(operator, tester.From, big.NewInt(100))
   736  	assert.NoError(t, err)
   737  	backend.Commit()
   738  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   739  
   740  	// Deploy ERC721
   741  	erc721Addr, tx, erc721, err := scnft.DeployServiceChainNFT(operator, backend, bridgeAddr)
   742  	assert.NoError(t, err)
   743  	backend.Commit()
   744  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   745  
   746  	// Register ERC721
   747  	tx, err = b.RegisterToken(operator, erc721Addr, erc721Addr)
   748  	assert.NoError(t, err)
   749  	backend.Commit()
   750  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   751  
   752  	// Mint token to tester
   753  	tx, err = erc721.RegisterBulk(operator, tester.From, big.NewInt(0), big.NewInt(10))
   754  	assert.NoError(t, err)
   755  	backend.Commit()
   756  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   757  
   758  	return &bridgeTokenTestENV{
   759  		backend,
   760  		operator,
   761  		tester,
   762  		b,
   763  		erc20,
   764  		erc721,
   765  		erc20Addr,
   766  		erc721Addr,
   767  	}
   768  }
   769  
   770  // TestBridgeContract_RegisterToken checks belows.
   771  // - RegisterToken works well
   772  // - DeregisterToken works well
   773  func TestBridgeContract_RegisterToken(t *testing.T) {
   774  	env := generateBridgeTokenTestEnv(t)
   775  	defer env.backend.Close()
   776  
   777  	backend := env.backend
   778  	operator := env.operator
   779  	b := env.bridge
   780  	erc20Addr := env.erc20Addr
   781  	erc721Addr := env.erc721Addr
   782  
   783  	// Deregister erc20
   784  	tx, err := b.DeregisterToken(operator, erc20Addr)
   785  	assert.NoError(t, err)
   786  	backend.Commit()
   787  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusSuccessful, t)
   788  
   789  	cpToken, err := b.RegisteredTokens(nil, erc20Addr)
   790  	assert.NoError(t, err)
   791  	assert.Equal(t, common.Address{}, cpToken)
   792  
   793  	cpToken, err = b.RegisteredTokens(nil, erc721Addr)
   794  	assert.NoError(t, err)
   795  	assert.Equal(t, erc721Addr, cpToken)
   796  
   797  	// Deregister erc721Addr
   798  	tx, err = b.DeregisterToken(operator, erc721Addr)
   799  	assert.NoError(t, err)
   800  	backend.Commit()
   801  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusSuccessful, t)
   802  
   803  	cpToken, err = b.RegisteredTokens(nil, erc721Addr)
   804  	assert.NoError(t, err)
   805  	assert.Equal(t, common.Address{}, cpToken)
   806  
   807  	tokens, err := b.GetRegisteredTokenList(nil)
   808  	assert.NoError(t, err)
   809  	assert.Equal(t, 0, len(tokens))
   810  
   811  	// Register erc20
   812  	tx, err = b.RegisterToken(operator, erc20Addr, erc20Addr)
   813  	assert.NoError(t, err)
   814  	backend.Commit()
   815  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusSuccessful, t)
   816  
   817  	cpToken, err = b.RegisteredTokens(nil, erc20Addr)
   818  	assert.NoError(t, err)
   819  	assert.Equal(t, erc20Addr, cpToken)
   820  
   821  	tx, err = b.RegisterToken(operator, erc20Addr, erc20Addr)
   822  	assert.NoError(t, err)
   823  	backend.Commit()
   824  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusErrExecutionReverted, t)
   825  
   826  	// Register erc721
   827  	tx, err = b.RegisterToken(operator, erc721Addr, erc721Addr)
   828  	assert.NoError(t, err)
   829  	backend.Commit()
   830  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusSuccessful, t)
   831  
   832  	cpToken, err = b.RegisteredTokens(nil, erc721Addr)
   833  	assert.NoError(t, err)
   834  	assert.Equal(t, erc721Addr, cpToken)
   835  
   836  	tx, err = b.RegisterToken(operator, erc721Addr, erc721Addr)
   837  	assert.NoError(t, err)
   838  	backend.Commit()
   839  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusErrExecutionReverted, t)
   840  
   841  	// Deregister erc721Addr
   842  	tx, err = b.DeregisterToken(operator, erc721Addr)
   843  	assert.NoError(t, err)
   844  	backend.Commit()
   845  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusSuccessful, t)
   846  
   847  	cpToken, err = b.RegisteredTokens(nil, erc721Addr)
   848  	assert.NoError(t, err)
   849  	assert.Equal(t, common.Address{}, cpToken)
   850  }
   851  
   852  // TestBridgeContract_InitStatus checks initial lock status.
   853  func TestBridgeContract_InitStatus(t *testing.T) {
   854  	env := generateBridgeTokenTestEnv(t)
   855  	defer env.backend.Close()
   856  
   857  	b := env.bridge
   858  	erc20Addr := env.erc20Addr
   859  	erc721Addr := env.erc721Addr
   860  
   861  	// initial value check
   862  	isLocked, err := b.LockedTokens(nil, erc20Addr)
   863  	assert.NoError(t, err)
   864  	assert.Equal(t, false, isLocked)
   865  
   866  	isLocked, err = b.LockedTokens(nil, erc721Addr)
   867  	assert.NoError(t, err)
   868  	assert.Equal(t, false, isLocked)
   869  
   870  	isLocked, err = b.IsLockedKLAY(nil)
   871  	assert.NoError(t, err)
   872  	assert.Equal(t, false, isLocked)
   873  }
   874  
   875  // TestBridgeContract_InitRequest checks the following:
   876  // - the request value transfer can be allowed after registering it.
   877  func TestBridgeContract_InitRequest(t *testing.T) {
   878  	env := generateBridgeTokenTestEnv(t)
   879  	defer env.backend.Close()
   880  
   881  	backend := env.backend
   882  	operator := env.operator
   883  	tester := env.tester
   884  	b := env.bridge
   885  	erc20 := env.erc20
   886  	erc721 := env.erc721
   887  
   888  	// check to allow value transfer
   889  	tx, err := erc20.RequestValueTransfer(tester, big.NewInt(1), operator.From, big.NewInt(0), nil)
   890  	assert.NoError(t, err)
   891  	backend.Commit()
   892  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   893  
   894  	tx, err = erc721.RequestValueTransfer(tester, big.NewInt(1), operator.From, nil)
   895  	assert.NoError(t, err)
   896  	backend.Commit()
   897  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   898  
   899  	tester.Value = big.NewInt(1)
   900  	tx, err = b.RequestKLAYTransfer(tester, tester.From, big.NewInt(1), nil)
   901  	assert.NoError(t, err)
   902  	backend.Commit()
   903  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
   904  	tester.Value = nil
   905  }
   906  
   907  // TestBridgeContract_TokenLock checks the following:
   908  // - the token can be lock to prevent value transfer requests.
   909  func TestBridgeContract_TokenLock(t *testing.T) {
   910  	env := generateBridgeTokenTestEnv(t)
   911  	defer env.backend.Close()
   912  
   913  	backend := env.backend
   914  	operator := env.operator
   915  	tester := env.tester
   916  	b := env.bridge
   917  	erc20 := env.erc20
   918  	erc721 := env.erc721
   919  	erc20Addr := env.erc20Addr
   920  	erc721Addr := env.erc721Addr
   921  
   922  	// lock token
   923  	tx, err := b.LockToken(operator, erc20Addr)
   924  	assert.NoError(t, err)
   925  	backend.Commit()
   926  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusSuccessful, t)
   927  
   928  	tx, err = b.LockToken(operator, erc721Addr)
   929  	assert.NoError(t, err)
   930  	backend.Commit()
   931  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusSuccessful, t)
   932  
   933  	tx, err = b.LockKLAY(operator)
   934  	assert.NoError(t, err)
   935  	backend.Commit()
   936  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusSuccessful, t)
   937  
   938  	// check value after locking
   939  	isLocked, err := b.LockedTokens(nil, erc20Addr)
   940  	assert.NoError(t, err)
   941  	assert.Equal(t, true, isLocked)
   942  
   943  	isLocked, err = b.LockedTokens(nil, erc721Addr)
   944  	assert.NoError(t, err)
   945  	assert.Equal(t, true, isLocked)
   946  
   947  	isLocked, err = b.IsLockedKLAY(nil)
   948  	assert.NoError(t, err)
   949  	assert.Equal(t, true, isLocked)
   950  
   951  	// check to prevent value transfer
   952  	tx, err = erc20.RequestValueTransfer(tester, big.NewInt(1), operator.From, big.NewInt(0), nil)
   953  	assert.NoError(t, err)
   954  	backend.Commit()
   955  	assert.NotNil(t, bind.CheckWaitMined(backend, tx))
   956  
   957  	tx, err = erc721.RequestValueTransfer(tester, big.NewInt(1), operator.From, nil)
   958  	assert.NoError(t, err)
   959  	backend.Commit()
   960  	assert.NotNil(t, bind.CheckWaitMined(backend, tx))
   961  
   962  	tester.Value = big.NewInt(1)
   963  	tx, err = b.RequestKLAYTransfer(tester, tester.From, big.NewInt(1), nil)
   964  	assert.NoError(t, err)
   965  	backend.Commit()
   966  	assert.NotNil(t, bind.CheckWaitMined(backend, tx))
   967  	tester.Value = nil
   968  }
   969  
   970  // TestBridgeContract_TokenLockFail checks the following:
   971  // - testing the case locking token is fail.
   972  func TestBridgeContract_TokenLockFail(t *testing.T) {
   973  	env := generateBridgeTokenTestEnv(t)
   974  	defer env.backend.Close()
   975  
   976  	backend := env.backend
   977  	operator := env.operator
   978  	tester := env.tester
   979  	b := env.bridge
   980  	erc20Addr := env.erc20Addr
   981  	erc721Addr := env.erc721Addr
   982  
   983  	// fail locking token by invalid owner.
   984  	tx, err := b.LockToken(tester, erc20Addr)
   985  	assert.NoError(t, err)
   986  	backend.Commit()
   987  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusErrExecutionReverted, t)
   988  
   989  	tx, err = b.LockToken(tester, erc721Addr)
   990  	assert.NoError(t, err)
   991  	backend.Commit()
   992  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusErrExecutionReverted, t)
   993  
   994  	tx, err = b.LockKLAY(tester)
   995  	assert.NoError(t, err)
   996  	backend.Commit()
   997  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusErrExecutionReverted, t)
   998  
   999  	// fail locking unregistered token.
  1000  	testAddr := common.BytesToAddress([]byte("unregistered"))
  1001  	tx, err = b.LockToken(operator, testAddr)
  1002  	assert.NoError(t, err)
  1003  	backend.Commit()
  1004  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusErrExecutionReverted, t)
  1005  
  1006  	// fail locking token if it is already locked.
  1007  	tx, err = b.LockToken(operator, erc20Addr)
  1008  	assert.NoError(t, err)
  1009  	backend.Commit()
  1010  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusSuccessful, t)
  1011  
  1012  	tx, err = b.LockToken(operator, erc721Addr)
  1013  	assert.NoError(t, err)
  1014  	backend.Commit()
  1015  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusSuccessful, t)
  1016  
  1017  	tx, err = b.LockKLAY(operator)
  1018  	assert.NoError(t, err)
  1019  	backend.Commit()
  1020  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusSuccessful, t)
  1021  
  1022  	tx, err = b.LockToken(operator, erc20Addr)
  1023  	assert.NoError(t, err)
  1024  	backend.Commit()
  1025  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusErrExecutionReverted, t)
  1026  
  1027  	tx, err = b.LockToken(operator, erc721Addr)
  1028  	assert.NoError(t, err)
  1029  	backend.Commit()
  1030  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusErrExecutionReverted, t)
  1031  
  1032  	tx, err = b.LockKLAY(operator)
  1033  	assert.NoError(t, err)
  1034  	backend.Commit()
  1035  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusErrExecutionReverted, t)
  1036  }
  1037  
  1038  // TestBridgeContract_TokenUnlockFail checks the following:
  1039  // - testing the case unlocking token is fail.
  1040  func TestBridgeContract_TokenUnlockFail(t *testing.T) {
  1041  	env := generateBridgeTokenTestEnv(t)
  1042  	defer env.backend.Close()
  1043  
  1044  	backend := env.backend
  1045  	operator := env.operator
  1046  	b := env.bridge
  1047  	erc20Addr := env.erc20Addr
  1048  	erc721Addr := env.erc721Addr
  1049  
  1050  	// fail locking unregistered token.
  1051  	testAddr := common.BytesToAddress([]byte("unregistered"))
  1052  	tx, err := b.UnlockToken(operator, testAddr)
  1053  	assert.NoError(t, err)
  1054  	backend.Commit()
  1055  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusErrExecutionReverted, t)
  1056  
  1057  	// fail locking token if it is already unlocked.
  1058  	tx, err = b.UnlockToken(operator, erc20Addr)
  1059  	assert.NoError(t, err)
  1060  	backend.Commit()
  1061  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusErrExecutionReverted, t)
  1062  
  1063  	tx, err = b.UnlockToken(operator, erc721Addr)
  1064  	assert.NoError(t, err)
  1065  	backend.Commit()
  1066  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusErrExecutionReverted, t)
  1067  
  1068  	tx, err = b.UnlockKLAY(operator)
  1069  	assert.NoError(t, err)
  1070  	backend.Commit()
  1071  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusErrExecutionReverted, t)
  1072  }
  1073  
  1074  // TestBridgeContract_CheckValueTransferAfterUnLock checks the following:
  1075  // - the token can be unlock to allow value transfer requests.
  1076  func TestBridgeContract_CheckValueTransferAfterUnLock(t *testing.T) {
  1077  	env := generateBridgeTokenTestEnv(t)
  1078  	defer env.backend.Close()
  1079  
  1080  	backend := env.backend
  1081  	operator := env.operator
  1082  	tester := env.tester
  1083  	b := env.bridge
  1084  	erc20 := env.erc20
  1085  	erc721 := env.erc721
  1086  	erc20Addr := env.erc20Addr
  1087  	erc721Addr := env.erc721Addr
  1088  
  1089  	// lock token
  1090  	tx, err := b.LockToken(operator, erc20Addr)
  1091  	assert.NoError(t, err)
  1092  	backend.Commit()
  1093  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusSuccessful, t)
  1094  
  1095  	tx, err = b.LockToken(operator, erc721Addr)
  1096  	assert.NoError(t, err)
  1097  	backend.Commit()
  1098  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusSuccessful, t)
  1099  
  1100  	tx, err = b.LockKLAY(operator)
  1101  	assert.NoError(t, err)
  1102  	backend.Commit()
  1103  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusSuccessful, t)
  1104  
  1105  	// unlock token
  1106  	tx, err = b.UnlockToken(operator, erc20Addr)
  1107  	assert.NoError(t, err)
  1108  	backend.Commit()
  1109  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusSuccessful, t)
  1110  
  1111  	tx, err = b.UnlockToken(operator, erc721Addr)
  1112  	assert.NoError(t, err)
  1113  	backend.Commit()
  1114  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusSuccessful, t)
  1115  
  1116  	tx, err = b.UnlockKLAY(operator)
  1117  	assert.NoError(t, err)
  1118  	backend.Commit()
  1119  	CheckReceipt(backend, tx, 1*time.Second, types.ReceiptStatusSuccessful, t)
  1120  
  1121  	// check value after unlocking
  1122  	isLocked, err := b.LockedTokens(nil, erc20Addr)
  1123  	assert.NoError(t, err)
  1124  	assert.Equal(t, false, isLocked)
  1125  
  1126  	isLocked, err = b.LockedTokens(nil, erc721Addr)
  1127  	assert.NoError(t, err)
  1128  	assert.Equal(t, false, isLocked)
  1129  
  1130  	isLocked, err = b.IsLockedKLAY(nil)
  1131  	assert.NoError(t, err)
  1132  	assert.Equal(t, false, isLocked)
  1133  
  1134  	// check to allow value transfer
  1135  	tx, err = erc20.RequestValueTransfer(tester, big.NewInt(1), operator.From, big.NewInt(0), nil)
  1136  	assert.NoError(t, err)
  1137  	backend.Commit()
  1138  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
  1139  
  1140  	tx, err = erc721.RequestValueTransfer(tester, big.NewInt(1), operator.From, nil)
  1141  	assert.NoError(t, err)
  1142  	backend.Commit()
  1143  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
  1144  
  1145  	tester.Value = big.NewInt(1)
  1146  	tx, err = b.RequestKLAYTransfer(tester, tester.From, big.NewInt(1), nil)
  1147  	assert.NoError(t, err)
  1148  	backend.Commit()
  1149  	assert.Nil(t, bind.CheckWaitMined(backend, tx))
  1150  	tester.Value = nil
  1151  }
  1152  
  1153  // TestBridgeRequestHandleGasUsed tests the gas used of handle function
  1154  // with the gap of lowerHandle nonce and handle nonce.
  1155  func TestBridgeRequestHandleGasUsed(t *testing.T) {
  1156  	// Generate a new random account and a funded simulator
  1157  	authKey, _ := crypto.GenerateKey()
  1158  	auth := bind.NewKeyedTransactor(authKey)
  1159  	auth.GasLimit = DefaultBridgeTxGasLimit
  1160  
  1161  	aliceKey, _ := crypto.GenerateKey()
  1162  	alice := bind.NewKeyedTransactor(aliceKey)
  1163  
  1164  	bobKey, _ := crypto.GenerateKey()
  1165  	bob := bind.NewKeyedTransactor(bobKey)
  1166  
  1167  	// Create Simulated backend
  1168  	alloc := blockchain.GenesisAlloc{
  1169  		alice.From: {Balance: big.NewInt(params.KLAY)},
  1170  		auth.From:  {Balance: big.NewInt(params.KLAY)},
  1171  	}
  1172  	sim := backends.NewSimulatedBackend(alloc)
  1173  	defer sim.Close()
  1174  
  1175  	var err error
  1176  
  1177  	// Deploy a bridge contract
  1178  	auth.Value = big.NewInt(100000000000)
  1179  	_, _, b, err := bridge.DeployBridge(auth, sim, false)
  1180  	assert.NoError(t, err)
  1181  	sim.Commit() // block
  1182  	auth.Value = big.NewInt(0)
  1183  
  1184  	// Register the owner as a signer
  1185  	_, err = b.RegisterOperator(&bind.TransactOpts{From: auth.From, Signer: auth.Signer, GasLimit: testGasLimit}, auth.From)
  1186  	assert.NoError(t, err)
  1187  	sim.Commit() // block
  1188  
  1189  	// Subscribe Bridge Contract
  1190  	handleValueTransferEventCh := make(chan *bridge.BridgeHandleValueTransfer, 10)
  1191  	handleValueTransferSub, err := b.WatchHandleValueTransfer(nil, handleValueTransferEventCh, nil, nil, nil)
  1192  	defer handleValueTransferSub.Unsubscribe()
  1193  
  1194  	handleFunc := func(nonce int) {
  1195  		hTx, err := b.HandleKLAYTransfer(auth, common.HexToHash(strconv.Itoa(nonce)), alice.From, bob.From, big.NewInt(1), uint64(nonce), uint64(1+nonce), nil)
  1196  		assert.NoError(t, err)
  1197  		sim.Commit()
  1198  
  1199  		receipt, err := bind.WaitMined(context.Background(), sim, hTx)
  1200  		assert.NoError(t, err)
  1201  		assert.Equal(t, uint(0x1), receipt.Status)
  1202  
  1203  		select {
  1204  		case ev := <-handleValueTransferEventCh:
  1205  			t.Log("Handle value transfer event",
  1206  				"handleNonce", ev.HandleNonce,
  1207  				"lowerHandleNonce", ev.LowerHandleNonce,
  1208  				"gasUsed", receipt.GasUsed,
  1209  				"status", receipt.Status)
  1210  		case <-time.After(1 * time.Second):
  1211  			if receipt != nil {
  1212  				t.Log("handle event omitted Tx gas used=", receipt.GasUsed)
  1213  			}
  1214  			t.Fatal("handle event omitted")
  1215  		}
  1216  	}
  1217  
  1218  	// handle 0 ~ 499 nonce
  1219  	for i := 0; i < 500; i++ {
  1220  		handleFunc(i)
  1221  	}
  1222  
  1223  	lowerHandleNonce, _ := b.LowerHandleNonce(nil)
  1224  	assert.Equal(t, uint64(500), lowerHandleNonce)
  1225  	upperHandleNonce, _ := b.UpperHandleNonce(nil)
  1226  	assert.Equal(t, uint64(499), upperHandleNonce)
  1227  
  1228  	// handle 501 ~ 999 nonce
  1229  	for i := 501; i < 1000; i++ {
  1230  		handleFunc(i)
  1231  	}
  1232  
  1233  	lowerHandleNonce, _ = b.LowerHandleNonce(nil)
  1234  	assert.Equal(t, uint64(500), lowerHandleNonce)
  1235  	upperHandleNonce, _ = b.UpperHandleNonce(nil)
  1236  	assert.Equal(t, uint64(999), upperHandleNonce)
  1237  
  1238  	// This 500 nonce handle checks whether the handle transaction which has a loop failed.
  1239  	handleFunc(500)
  1240  
  1241  	lowerHandleNonce, _ = b.LowerHandleNonce(nil)
  1242  	assert.Equal(t, uint64(701), lowerHandleNonce)
  1243  	upperHandleNonce, _ = b.UpperHandleNonce(nil)
  1244  	assert.Equal(t, uint64(999), upperHandleNonce)
  1245  }
  1246  
  1247  // TestBridgeMaxOperator tests
  1248  // - the gas used of handle function with max operators.
  1249  // - preventing to add more operators than the limit.
  1250  func TestBridgeMaxOperatorHandleTxGasUsed(t *testing.T) {
  1251  	// Generate a new random account and a funded simulator
  1252  	maxOperator := 12
  1253  
  1254  	var authList []*bind.TransactOpts
  1255  	for i := 0; i <= maxOperator; i++ {
  1256  		authKey, _ := crypto.GenerateKey()
  1257  		authList = append(authList, bind.NewKeyedTransactor(authKey))
  1258  		authList[i].GasLimit = DefaultBridgeTxGasLimit
  1259  	}
  1260  	auth := authList[0]
  1261  
  1262  	aliceKey, _ := crypto.GenerateKey()
  1263  	alice := bind.NewKeyedTransactor(aliceKey)
  1264  
  1265  	bobKey, _ := crypto.GenerateKey()
  1266  	bob := bind.NewKeyedTransactor(bobKey)
  1267  
  1268  	// Create Simulated backend
  1269  	alloc := blockchain.GenesisAlloc{
  1270  		alice.From: {Balance: big.NewInt(params.KLAY)},
  1271  		auth.From:  {Balance: big.NewInt(params.KLAY)},
  1272  	}
  1273  	sim := backends.NewSimulatedBackend(alloc)
  1274  	defer sim.Close()
  1275  
  1276  	var err error
  1277  
  1278  	// Deploy a bridge contract
  1279  	auth.Value = big.NewInt(100000000000)
  1280  	_, _, b, err := bridge.DeployBridge(auth, sim, false)
  1281  	assert.NoError(t, err)
  1282  	sim.Commit() // block
  1283  	auth.Value = big.NewInt(0)
  1284  
  1285  	// Register the owner as a signer
  1286  	for _, a := range authList {
  1287  		_, err = b.RegisterOperator(&bind.TransactOpts{From: auth.From, Signer: auth.Signer, GasLimit: testGasLimit}, a.From)
  1288  		assert.NoError(t, err)
  1289  	}
  1290  
  1291  	_, err = b.SetOperatorThreshold(&bind.TransactOpts{From: auth.From, Signer: auth.Signer, GasLimit: testGasLimit}, voteTypeValueTransfer, uint8(maxOperator))
  1292  	assert.NoError(t, err)
  1293  
  1294  	sim.Commit() // block
  1295  
  1296  	// test preventing more operators than the limit.
  1297  	{
  1298  		tx, err := b.RegisterOperator(&bind.TransactOpts{From: auth.From, Signer: auth.Signer, GasLimit: testGasLimit}, authList[maxOperator].From)
  1299  		assert.NoError(t, err)
  1300  		sim.Commit() // block
  1301  
  1302  		receipt, err := bind.WaitMined(context.Background(), sim, tx)
  1303  		assert.NoError(t, err)
  1304  		assert.Equal(t, types.ReceiptStatusErrExecutionReverted, receipt.Status)
  1305  	}
  1306  
  1307  	// Subscribe Bridge Contract
  1308  	handleValueTransferEventCh := make(chan *bridge.BridgeHandleValueTransfer, 10)
  1309  	handleValueTransferSub, err := b.WatchHandleValueTransfer(nil, handleValueTransferEventCh, nil, nil, nil)
  1310  	defer handleValueTransferSub.Unsubscribe()
  1311  
  1312  	handleFunc := func(a *bind.TransactOpts, nonce int) {
  1313  		hTx, err := b.HandleKLAYTransfer(a, common.HexToHash(strconv.Itoa(nonce)), alice.From, bob.From, big.NewInt(1), uint64(nonce), uint64(1+nonce), nil)
  1314  		assert.NoError(t, err)
  1315  		sim.Commit()
  1316  
  1317  		receipt, err := bind.WaitMined(context.Background(), sim, hTx)
  1318  		assert.NoError(t, err)
  1319  		assert.Equal(t, uint(0x1), receipt.Status)
  1320  
  1321  		t.Log("Handle value transfer tx receipt", "gasUsed", receipt.GasUsed, "status", receipt.Status)
  1322  	}
  1323  
  1324  	for i := 0; i < maxOperator; i++ {
  1325  		handleFunc(authList[i], 0)
  1326  	}
  1327  
  1328  	select {
  1329  	case ev := <-handleValueTransferEventCh:
  1330  		t.Log("Handle value transfer event",
  1331  			"handleNonce", ev.HandleNonce,
  1332  			"lowerHandleNonce", ev.LowerHandleNonce)
  1333  	case <-time.After(1 * time.Second):
  1334  		t.Fatal("handle event omitted")
  1335  	}
  1336  }
  1337  
  1338  // TestBridgeThresholdLimit tests preventing the invalid threshold value.
  1339  func TestBridgeThresholdLimit(t *testing.T) {
  1340  	// Generate a new random account and a funded simulator
  1341  	maxOperator := 12
  1342  
  1343  	var authList []*bind.TransactOpts
  1344  	for i := 0; i < maxOperator; i++ {
  1345  		authKey, _ := crypto.GenerateKey()
  1346  		authList = append(authList, bind.NewKeyedTransactor(authKey))
  1347  		authList[i].GasLimit = DefaultBridgeTxGasLimit
  1348  	}
  1349  	auth := authList[0]
  1350  
  1351  	// Create Simulated backend
  1352  	alloc := blockchain.GenesisAlloc{
  1353  		auth.From: {Balance: big.NewInt(params.KLAY)},
  1354  	}
  1355  	sim := backends.NewSimulatedBackend(alloc)
  1356  	defer sim.Close()
  1357  
  1358  	var err error
  1359  
  1360  	// Deploy a bridge contract
  1361  	auth.Value = big.NewInt(100000000000)
  1362  	_, _, b, err := bridge.DeployBridge(auth, sim, false)
  1363  	assert.NoError(t, err)
  1364  	sim.Commit() // block
  1365  	auth.Value = big.NewInt(0)
  1366  
  1367  	// Register the owner as a signer
  1368  	for i, a := range authList {
  1369  		_, err = b.RegisterOperator(&bind.TransactOpts{From: auth.From, Signer: auth.Signer, GasLimit: testGasLimit}, a.From)
  1370  		assert.NoError(t, err)
  1371  		sim.Commit() // block
  1372  
  1373  		// bigger threshold than operators
  1374  		{
  1375  			tx, err := b.SetOperatorThreshold(&bind.TransactOpts{From: auth.From, Signer: auth.Signer, GasLimit: testGasLimit}, voteTypeValueTransfer, uint8(i+2))
  1376  			assert.NoError(t, err)
  1377  			sim.Commit() // block
  1378  
  1379  			receipt, err := bind.WaitMined(context.Background(), sim, tx)
  1380  			assert.NoError(t, err)
  1381  			assert.Equal(t, types.ReceiptStatusErrExecutionReverted, receipt.Status)
  1382  		}
  1383  
  1384  		// zero threshold
  1385  		{
  1386  			tx, err := b.SetOperatorThreshold(&bind.TransactOpts{From: auth.From, Signer: auth.Signer, GasLimit: testGasLimit}, voteTypeValueTransfer, uint8(0))
  1387  			assert.NoError(t, err)
  1388  			sim.Commit() // block
  1389  
  1390  			receipt, err := bind.WaitMined(context.Background(), sim, tx)
  1391  			assert.NoError(t, err)
  1392  			assert.Equal(t, types.ReceiptStatusErrExecutionReverted, receipt.Status)
  1393  		}
  1394  
  1395  		// same threshold with operators
  1396  		{
  1397  			tx, err := b.SetOperatorThreshold(&bind.TransactOpts{From: auth.From, Signer: auth.Signer, GasLimit: testGasLimit}, voteTypeValueTransfer, uint8(i+1))
  1398  			assert.NoError(t, err)
  1399  			sim.Commit() // block
  1400  
  1401  			receipt, err := bind.WaitMined(context.Background(), sim, tx)
  1402  			assert.NoError(t, err)
  1403  			assert.Equal(t, types.ReceiptStatusSuccessful, receipt.Status)
  1404  		}
  1405  
  1406  		// lower threshold than operator
  1407  		if i > 0 {
  1408  			tx, err := b.SetOperatorThreshold(&bind.TransactOpts{From: auth.From, Signer: auth.Signer, GasLimit: testGasLimit}, voteTypeValueTransfer, uint8(i))
  1409  			assert.NoError(t, err)
  1410  			sim.Commit() // block
  1411  
  1412  			receipt, err := bind.WaitMined(context.Background(), sim, tx)
  1413  			assert.NoError(t, err)
  1414  			assert.Equal(t, types.ReceiptStatusSuccessful, receipt.Status)
  1415  		}
  1416  	}
  1417  }