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 }