github.com/0chain/gosdk@v1.17.11/zcnbridge/bridge_test.go (about) 1 package zcnbridge 2 3 import ( 4 "context" 5 "encoding/hex" 6 "encoding/json" 7 "github.com/0chain/gosdk/zcnbridge/ethereum/uniswapnetwork" 8 "github.com/ethereum/go-ethereum/accounts/abi" 9 "log" 10 "math/big" 11 "os" 12 "path" 13 "strconv" 14 "testing" 15 "time" 16 17 "github.com/0chain/gosdk/zcnbridge/ethereum/zcntoken" 18 19 sdkcommon "github.com/0chain/gosdk/core/common" 20 "github.com/0chain/gosdk/zcnbridge/ethereum" 21 "github.com/0chain/gosdk/zcnbridge/ethereum/authorizers" 22 binding "github.com/0chain/gosdk/zcnbridge/ethereum/bridge" 23 bridgemocks "github.com/0chain/gosdk/zcnbridge/mocks" 24 "github.com/0chain/gosdk/zcnbridge/transaction" 25 transactionmocks "github.com/0chain/gosdk/zcnbridge/transaction/mocks" 26 "github.com/0chain/gosdk/zcnbridge/wallet" 27 "github.com/0chain/gosdk/zcnbridge/zcnsc" 28 "github.com/0chain/gosdk/zcncore" 29 eth "github.com/ethereum/go-ethereum" 30 "github.com/ethereum/go-ethereum/accounts" 31 "github.com/ethereum/go-ethereum/accounts/keystore" 32 "github.com/ethereum/go-ethereum/common" 33 "github.com/spf13/viper" 34 "github.com/stretchr/testify/mock" 35 "github.com/stretchr/testify/require" 36 ) 37 38 const ( 39 ethereumAddress = "0xD8c9156e782C68EE671C09b6b92de76C97948432" 40 41 alchemyEthereumNodeURL = "https://eth-mainnet.g.alchemy.com/v2/9VanLUbRE0pLmDHwCHGJlhs9GHosrfD9" 42 tenderlyEthereumNodeURL = "https://rpc.tenderly.co/fork/835ecb4e-1f60-4129-adc2-b0c741193839" 43 infuraEthereumNodeURL = "https://mainnet.infura.io/v3/7238211010344719ad14a89db874158c" 44 45 password = "02289b9" 46 47 authorizerDelegatedAddress = "0xa149B58b7e1390D152383BB03dBc79B390F648e2" 48 49 bridgeAddress = "0x7bbbEa24ac1751317D7669f05558632c4A9113D7" 50 tokenAddress = "0xb9EF770B6A5e12E45983C5D80545258aA38F3B78" 51 authorizersAddress = "0xEAe8229c0E457efBA1A1769e7F8c20110fF68E61" 52 uniswapAddress = "0x4c12C2FeEDD86267d17dB64BaB2cFD12cD8611f5" 53 54 zcnTxnID = "b26abeb31fcee5d2e75b26717722938a06fa5ce4a5b5e68ddad68357432caace" 55 amount = 1 56 txnFee = 1 57 nonce = 1 58 59 ethereumTxnID = "0x3b59971c2aa294739cd73912f0c5a7996aafb796238cf44408b0eb4af0fbac82" 60 61 clientId = "d6e9b3222434faa043c683d1a939d6a0fa2818c4d56e794974d64a32005330d3" 62 ) 63 64 var ( 65 uniswapSmartContractCode = "60806040526004361061002d5760003560e01c806318ae74a41461003957806397a40b341461006957610034565b3661003457005b600080fd5b610053600480360381019061004e9190610781565b6100a6565b60405161006091906107bd565b60405180910390f35b34801561007557600080fd5b50610090600480360381019061008b91906107d8565b61017e565b60405161009d91906107bd565b60405180910390f35b60008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fb3bdb4134856100ef61061a565b33426040518663ffffffff1660e01b81526004016101109493929190610917565b60006040518083038185885af115801561012e573d6000803e3d6000fd5b50505050506040513d6000823e3d601f19601f820116820180604052508101906101589190610ad1565b90508060018151811061016e5761016d610b1a565b5b6020026020010151915050919050565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856040518463ffffffff1660e01b81526004016101df93929190610b49565b6020604051808303816000875af11580156101fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102229190610bb8565b50600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b360008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040518363ffffffff1660e01b81526004016102a0929190610be5565b6020604051808303816000875af11580156102bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102e39190610bb8565b506060600367ffffffffffffffff81111561030157610300610979565b5b60405190808252806020026020018201604052801561032f5781602001602082028036833780820191505090505b50905073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488160008151811061035b5761035a610b1a565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2816001815181106103be576103bd610b1a565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9ef770b6a5e12e45983c5d80545258aa38f3b788160028151811061042157610420610b1a565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638803dbee86868533426040518663ffffffff1660e01b81526004016104bf959493929190610c0e565b6000604051808303816000875af11580156104de573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906105079190610ad1565b9050838160008151811061051e5761051d610b1a565b5b602002602001015110156105f457600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb338360008151811061057f5761057e610b1a565b5b6020026020010151876105929190610c97565b6040518363ffffffff1660e01b81526004016105af929190610be5565b6020604051808303816000875af11580156105ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f29190610bb8565b505b8060028151811061060857610607610b1a565b5b60200260200101519250505092915050565b60606000600267ffffffffffffffff81111561063957610638610979565b5b6040519080825280602002602001820160405280156106675781602001602082028036833780820191505090505b50905073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160008151811061069357610692610b1a565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b9ef770b6a5e12e45983c5d80545258aa38f3b78816001815181106106f6576106f5610b1a565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508091505090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b61075e8161074b565b811461076957600080fd5b50565b60008135905061077b81610755565b92915050565b60006020828403121561079757610796610741565b5b60006107a58482850161076c565b91505092915050565b6107b78161074b565b82525050565b60006020820190506107d260008301846107ae565b92915050565b600080604083850312156107ef576107ee610741565b5b60006107fd8582860161076c565b925050602061080e8582860161076c565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061086f82610844565b9050919050565b61087f81610864565b82525050565b60006108918383610876565b60208301905092915050565b6000602082019050919050565b60006108b582610818565b6108bf8185610823565b93506108ca83610834565b8060005b838110156108fb5781516108e28882610885565b97506108ed8361089d565b9250506001810190506108ce565b5085935050505092915050565b61091181610864565b82525050565b600060808201905061092c60008301876107ae565b818103602083015261093e81866108aa565b905061094d6040830185610908565b61095a60608301846107ae565b95945050505050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6109b182610968565b810181811067ffffffffffffffff821117156109d0576109cf610979565b5b80604052505050565b60006109e3610737565b90506109ef82826109a8565b919050565b600067ffffffffffffffff821115610a0f57610a0e610979565b5b602082029050602081019050919050565b600080fd5b600081519050610a3481610755565b92915050565b6000610a4d610a48846109f4565b6109d9565b90508083825260208201905060208402830185811115610a7057610a6f610a20565b5b835b81811015610a995780610a858882610a25565b845260208401935050602081019050610a72565b5050509392505050565b600082601f830112610ab857610ab7610963565b5b8151610ac8848260208601610a3a565b91505092915050565b600060208284031215610ae757610ae6610741565b5b600082015167ffffffffffffffff811115610b0557610b04610746565b5b610b1184828501610aa3565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000606082019050610b5e6000830186610908565b610b6b6020830185610908565b610b7860408301846107ae565b949350505050565b60008115159050919050565b610b9581610b80565b8114610ba057600080fd5b50565b600081519050610bb281610b8c565b92915050565b600060208284031215610bce57610bcd610741565b5b6000610bdc84828501610ba3565b91505092915050565b6000604082019050610bfa6000830185610908565b610c0760208301846107ae565b9392505050565b600060a082019050610c2360008301886107ae565b610c3060208301876107ae565b8181036040830152610c4281866108aa565b9050610c516060830185610908565b610c5e60808301846107ae565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610ca28261074b565b9150610cad8361074b565b9250828203905081811115610cc557610cc4610c68565b5b9291505056fea26469706673582212207de082f4e5f623e928f9b99a8e233f194bacc23969b40ea49a470ecfd2a1fb8464736f6c63430008140033" 66 ) 67 68 var ( 69 testKeyStoreLocation = path.Join(".", EthereumWalletStorageDir) 70 ) 71 72 var ( 73 ethereumSignatures = []*ethereum.AuthorizerSignature{ 74 { 75 ID: "0x2ec8F26ccC678c9faF0Df20208aEE3AF776160CD", 76 Signature: []byte("0xEAe8229c0E457efBA1A1769e7F8c20110fF68E61"), 77 }, 78 } 79 80 zcnScSignatures = []*zcnsc.AuthorizerSignature{ 81 { 82 ID: "0x2ec8F26ccC678c9faF0Df20208aEE3AF776160CD", 83 Signature: "0xEAe8229c0E457efBA1A1769e7F8c20110fF68E61", 84 }, 85 } 86 ) 87 88 type ethereumClientMock struct { 89 mock.TestingT 90 } 91 92 func (ecm *ethereumClientMock) Cleanup(callback func()) { 93 callback() 94 } 95 96 type transactionMock struct { 97 mock.TestingT 98 } 99 100 func (tem *transactionMock) Cleanup(callback func()) { 101 callback() 102 } 103 104 type transactionProviderMock struct { 105 mock.TestingT 106 } 107 108 func (tem *transactionProviderMock) Cleanup(callback func()) { 109 callback() 110 } 111 112 type keyStoreMock struct { 113 mock.TestingT 114 } 115 116 func (ksm *keyStoreMock) Cleanup(callback func()) { 117 callback() 118 } 119 120 type authorizerConfigTarget struct { 121 Fee sdkcommon.Balance `json:"fee"` 122 } 123 124 type authorizerNodeTarget struct { 125 ID string `json:"id"` 126 PublicKey string `json:"public_key"` 127 URL string `json:"url"` 128 Config *authorizerConfigTarget `json:"config"` 129 } 130 131 type authorizerConfigSource struct { 132 Fee string `json:"fee"` 133 } 134 135 type authorizerNodeSource struct { 136 ID string `json:"id"` 137 Config *authorizerConfigSource `json:"config"` 138 } 139 140 func (an *authorizerNodeTarget) decode(input []byte) error { 141 var objMap map[string]*json.RawMessage 142 err := json.Unmarshal(input, &objMap) 143 if err != nil { 144 return err 145 } 146 147 id, ok := objMap["id"] 148 if ok { 149 var idStr *string 150 err = json.Unmarshal(*id, &idStr) 151 if err != nil { 152 return err 153 } 154 an.ID = *idStr 155 } 156 157 pk, ok := objMap["public_key"] 158 if ok { 159 var pkStr *string 160 err = json.Unmarshal(*pk, &pkStr) 161 if err != nil { 162 return err 163 } 164 an.PublicKey = *pkStr 165 } 166 167 url, ok := objMap["url"] 168 if ok { 169 var urlStr *string 170 err = json.Unmarshal(*url, &urlStr) 171 if err != nil { 172 return err 173 } 174 an.URL = *urlStr 175 } 176 177 rawCfg, ok := objMap["config"] 178 if ok { 179 var cfg = &authorizerConfigTarget{} 180 err = cfg.decode(*rawCfg) 181 if err != nil { 182 return err 183 } 184 185 an.Config = cfg 186 } 187 188 return nil 189 } 190 191 func (c *authorizerConfigTarget) decode(input []byte) (err error) { 192 const ( 193 Fee = "fee" 194 ) 195 196 var objMap map[string]*json.RawMessage 197 err = json.Unmarshal(input, &objMap) 198 if err != nil { 199 return err 200 } 201 202 fee, ok := objMap[Fee] 203 if ok { 204 var feeStr *string 205 err = json.Unmarshal(*fee, &feeStr) 206 if err != nil { 207 return err 208 } 209 210 var balance, err = strconv.ParseInt(*feeStr, 10, 64) 211 if err != nil { 212 return err 213 } 214 215 c.Fee = sdkcommon.Balance(balance) 216 } 217 218 return nil 219 } 220 221 func getEthereumClient(t mock.TestingT) *bridgemocks.EthereumClient { 222 return bridgemocks.NewEthereumClient(ðereumClientMock{t}) 223 } 224 225 func getBridgeClient(ethereumNodeURL string, ethereumClient EthereumClient, transactionProvider transaction.TransactionProvider, keyStore KeyStore) *BridgeClient { 226 cfg := viper.New() 227 228 tempConfigFile, err := os.CreateTemp(".", "config.yaml") 229 if err != nil { 230 log.Fatalln(err) 231 } 232 233 defer func(name string) { 234 err := os.Remove(name) 235 if err != nil { 236 log.Fatalln(err) 237 } 238 }(tempConfigFile.Name()) 239 240 cfg.SetConfigFile(tempConfigFile.Name()) 241 242 cfg.SetDefault("bridge.bridge_address", bridgeAddress) 243 cfg.SetDefault("bridge.token_address", tokenAddress) 244 cfg.SetDefault("bridge.authorizers_address", authorizersAddress) 245 cfg.SetDefault("bridge.uniswap_address", uniswapAddress) 246 cfg.SetDefault("bridge.ethereum_address", ethereumAddress) 247 cfg.SetDefault("bridge.password", password) 248 cfg.SetDefault("bridge.gas_limit", 0) 249 cfg.SetDefault("bridge.consensus_threshold", 0) 250 251 return NewBridgeClient( 252 cfg.GetString("bridge.bridge_address"), 253 cfg.GetString("bridge.token_address"), 254 cfg.GetString("bridge.authorizers_address"), 255 cfg.GetString("bridge.uniswap_address"), 256 cfg.GetString("bridge.ethereum_address"), 257 ethereumNodeURL, 258 cfg.GetString("bridge.password"), 259 cfg.GetUint64("bridge.gas_limit"), 260 cfg.GetFloat64("bridge.consensus_threshold"), 261 262 ethereumClient, 263 transactionProvider, 264 keyStore, 265 ) 266 } 267 268 func prepareEthereumClientGeneralMockCalls(ethereumClient *mock.Mock) { 269 ethereumClient.On("EstimateGas", mock.Anything, mock.Anything).Return(uint64(400000), nil) 270 ethereumClient.On("ChainID", mock.Anything).Return(big.NewInt(400000), nil) 271 ethereumClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(nonce), nil) 272 ethereumClient.On("SuggestGasPrice", mock.Anything).Return(big.NewInt(400000), nil) 273 ethereumClient.On("SendTransaction", mock.Anything, mock.Anything).Return(nil) 274 } 275 276 func getTransaction(t mock.TestingT) *transactionmocks.Transaction { 277 return transactionmocks.NewTransaction(&transactionMock{t}) 278 } 279 280 func prepareTransactionGeneralMockCalls(transaction *mock.Mock) { 281 transaction.On("ExecuteSmartContract", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(zcnTxnID, nil) 282 transaction.On("Verify", mock.Anything).Return(nil) 283 } 284 285 func getTransactionProvider(t mock.TestingT) *transactionmocks.TransactionProvider { 286 return transactionmocks.NewTransactionProvider(&transactionProviderMock{t}) 287 } 288 289 func prepareTransactionProviderGeneralMockCalls(transactionProvider *mock.Mock, transaction *transactionmocks.Transaction) { 290 transactionProvider.On("NewTransactionEntity", mock.Anything).Return(transaction, nil) 291 } 292 293 func getKeyStore(t mock.TestingT) *bridgemocks.KeyStore { 294 return bridgemocks.NewKeyStore(&keyStoreMock{t}) 295 } 296 297 func prepareKeyStoreGeneralMockCalls(keyStore *bridgemocks.KeyStore) { 298 ks := keystore.NewKeyStore(testKeyStoreLocation, keystore.StandardScryptN, keystore.StandardScryptP) 299 300 keyStore.On("Find", mock.Anything).Return(accounts.Account{Address: common.HexToAddress(ethereumAddress)}, nil) 301 keyStore.On("TimedUnlock", mock.Anything, mock.Anything, mock.Anything).Run( 302 func(args mock.Arguments) { 303 err := ks.TimedUnlock(args.Get(0).(accounts.Account), args.Get(1).(string), args.Get(2).(time.Duration)) 304 if err != nil { 305 log.Fatalln(err) 306 } 307 }, 308 ).Return(nil) 309 keyStore.On("SignHash", mock.Anything, mock.Anything).Return([]byte(ethereumAddress), nil) 310 311 keyStore.On("GetEthereumKeyStore").Return(ks) 312 } 313 314 func Test_ZCNBridge(t *testing.T) { 315 ethereumClient := getEthereumClient(t) 316 prepareEthereumClientGeneralMockCalls(ðereumClient.Mock) 317 318 tx := getTransaction(t) 319 prepareTransactionGeneralMockCalls(&tx.Mock) 320 321 transactionProvider := getTransactionProvider(t) 322 prepareTransactionProviderGeneralMockCalls(&transactionProvider.Mock, tx) 323 324 keyStore := getKeyStore(t) 325 prepareKeyStoreGeneralMockCalls(keyStore) 326 327 bridgeClient := getBridgeClient(alchemyEthereumNodeURL, ethereumClient, transactionProvider, keyStore) 328 329 t.Run("should update authorizer config.", func(t *testing.T) { 330 source := &authorizerNodeSource{ 331 ID: "12345678", 332 Config: &authorizerConfigSource{ 333 Fee: "999", 334 }, 335 } 336 target := &authorizerNodeTarget{} 337 338 bytes, err := json.Marshal(source) 339 require.NoError(t, err) 340 341 err = target.decode(bytes) 342 require.NoError(t, err) 343 344 require.Equal(t, "", target.URL) 345 require.Equal(t, "", target.PublicKey) 346 require.Equal(t, "12345678", target.ID) 347 require.Equal(t, sdkcommon.Balance(999), target.Config.Fee) 348 }) 349 350 t.Run("should check configuration formating in MintWZCN", func(t *testing.T) { 351 _, err := bridgeClient.MintWZCN(context.Background(), ðereum.MintPayload{ 352 ZCNTxnID: zcnTxnID, 353 Amount: amount, 354 To: ethereumAddress, 355 Nonce: nonce, 356 Signatures: ethereumSignatures, 357 }) 358 require.NoError(t, err) 359 360 var sigs [][]byte 361 for _, signature := range ethereumSignatures { 362 sigs = append(sigs, signature.Signature) 363 } 364 365 to := common.HexToAddress(bridgeAddress) 366 fromAddress := common.HexToAddress(ethereumAddress) 367 368 rawAbi, err := binding.BridgeMetaData.GetAbi() 369 require.NoError(t, err) 370 371 pack, err := rawAbi.Pack("mint", common.HexToAddress(ethereumAddress), 372 big.NewInt(amount), 373 DefaultClientIDEncoder(zcnTxnID), 374 big.NewInt(nonce), 375 sigs) 376 require.NoError(t, err) 377 378 require.True(t, ethereumClient.AssertCalled( 379 t, 380 "EstimateGas", 381 context.Background(), 382 eth.CallMsg{ 383 To: &to, 384 From: fromAddress, 385 Data: pack, 386 }, 387 )) 388 }) 389 390 t.Run("should check configuration formating in BurnWZCN", func(t *testing.T) { 391 _, err := bridgeClient.BurnWZCN(context.Background(), amount) 392 require.NoError(t, err) 393 394 to := common.HexToAddress(bridgeAddress) 395 fromAddress := common.HexToAddress(ethereumAddress) 396 397 rawAbi, err := binding.BridgeMetaData.GetAbi() 398 require.NoError(t, err) 399 400 pack, err := rawAbi.Pack("burn", big.NewInt(amount), DefaultClientIDEncoder(zcncore.GetClientWalletID())) 401 require.NoError(t, err) 402 403 require.True(t, ethereumClient.AssertCalled( 404 t, 405 "EstimateGas", 406 context.Background(), 407 eth.CallMsg{ 408 To: &to, 409 From: fromAddress, 410 Data: pack, 411 }, 412 )) 413 }) 414 415 t.Run("should check configuration used by MintZCN", func(t *testing.T) { 416 payload := &zcnsc.MintPayload{ 417 EthereumTxnID: ethereumTxnID, 418 Amount: sdkcommon.Balance(amount), 419 Nonce: nonce, 420 Signatures: zcnScSignatures, 421 ReceivingClientID: clientId, 422 } 423 424 _, err := bridgeClient.MintZCN(context.Background(), payload) 425 require.NoError(t, err) 426 427 require.True(t, tx.AssertCalled( 428 t, 429 "ExecuteSmartContract", 430 context.Background(), 431 wallet.ZCNSCSmartContractAddress, 432 wallet.MintFunc, 433 payload, 434 uint64(0), 435 )) 436 }) 437 438 t.Run("should check configuration used by BurnZCN", func(t *testing.T) { 439 _, err := bridgeClient.BurnZCN(context.Background(), amount, txnFee) 440 require.NoError(t, err) 441 442 require.True(t, tx.AssertCalled( 443 t, 444 "ExecuteSmartContract", 445 context.Background(), 446 wallet.ZCNSCSmartContractAddress, 447 wallet.BurnFunc, 448 zcnsc.BurnPayload{ 449 EthereumAddress: ethereumAddress, 450 }, 451 uint64(amount), 452 )) 453 }) 454 455 t.Run("should check configuration used by AddEthereumAuthorizer", func(t *testing.T) { 456 _, err := bridgeClient.AddEthereumAuthorizer(context.Background(), common.HexToAddress(authorizerDelegatedAddress)) 457 require.NoError(t, err) 458 459 to := common.HexToAddress(authorizersAddress) 460 fromAddress := common.HexToAddress(ethereumAddress) 461 462 rawAbi, err := authorizers.AuthorizersMetaData.GetAbi() 463 require.NoError(t, err) 464 465 pack, err := rawAbi.Pack("addAuthorizers", common.HexToAddress(authorizerDelegatedAddress)) 466 require.NoError(t, err) 467 468 require.True(t, ethereumClient.AssertCalled( 469 t, 470 "EstimateGas", 471 context.Background(), 472 eth.CallMsg{ 473 To: &to, 474 From: fromAddress, 475 Data: pack, 476 }, 477 )) 478 }) 479 480 t.Run("should check configuration used by RemoveAuthorizer", func(t *testing.T) { 481 _, err := bridgeClient.RemoveEthereumAuthorizer(context.Background(), common.HexToAddress(authorizerDelegatedAddress)) 482 require.NoError(t, err) 483 484 to := common.HexToAddress(authorizersAddress) 485 fromAddress := common.HexToAddress(ethereumAddress) 486 487 rawAbi, err := authorizers.AuthorizersMetaData.GetAbi() 488 require.NoError(t, err) 489 490 pack, err := rawAbi.Pack("removeAuthorizers", common.HexToAddress(authorizerDelegatedAddress)) 491 require.NoError(t, err) 492 493 require.True(t, ethereumClient.AssertCalled( 494 t, 495 "EstimateGas", 496 context.Background(), 497 eth.CallMsg{ 498 To: &to, 499 From: fromAddress, 500 Data: pack, 501 }, 502 )) 503 }) 504 505 t.Run("should check configuration used by IncreaseBurnerAllowance", func(t *testing.T) { 506 _, err := bridgeClient.IncreaseBurnerAllowance(context.Background(), amount) 507 require.NoError(t, err) 508 509 spenderAddress := common.HexToAddress(bridgeAddress) 510 511 to := common.HexToAddress(tokenAddress) 512 fromAddress := common.HexToAddress(ethereumAddress) 513 514 rawAbi, err := zcntoken.TokenMetaData.GetAbi() 515 require.NoError(t, err) 516 517 pack, err := rawAbi.Pack("increaseApproval", spenderAddress, big.NewInt(amount)) 518 require.NoError(t, err) 519 520 require.True(t, ethereumClient.AssertCalled( 521 t, 522 "EstimateGas", 523 context.Background(), 524 eth.CallMsg{ 525 To: &to, 526 From: fromAddress, 527 Data: pack, 528 }, 529 )) 530 }) 531 532 t.Run("should check configuration used by SwapETH", func(t *testing.T) { 533 uniswapSmartContractCodeRaw, err := hex.DecodeString(uniswapSmartContractCode) 534 require.NoError(t, err) 535 536 ethereumClient.On("PendingCodeAt", mock.Anything, mock.Anything).Return(uniswapSmartContractCodeRaw, nil) 537 538 _, err = bridgeClient.SwapETH(context.Background(), amount, amount) 539 require.NoError(t, err) 540 541 // 1. To address parameter. 542 to := common.HexToAddress(bridgeClient.UniswapAddress) 543 544 // 2. From address parameter. 545 from := common.HexToAddress(bridgeClient.EthereumAddress) 546 547 // 3. Swap amount parameter 548 swapAmount := big.NewInt(amount) 549 550 var rawAbi *abi.ABI 551 552 rawAbi, err = uniswapnetwork.UniswapMetaData.GetAbi() 553 require.NoError(t, err) 554 555 var pack []byte 556 557 pack, err = rawAbi.Pack("swapETHForZCNExactAmountOut", swapAmount) 558 require.NoError(t, err) 559 560 require.True(t, ethereumClient.AssertCalled( 561 t, 562 "EstimateGas", 563 context.Background(), 564 eth.CallMsg{ 565 To: &to, 566 From: from, 567 Data: pack, 568 Value: swapAmount, 569 GasPrice: big.NewInt(400000), 570 }, 571 )) 572 }) 573 574 t.Run("should check configuration used by SwapUSDC", func(t *testing.T) { 575 uniswapSmartContractCodeRaw, err := hex.DecodeString(uniswapSmartContractCode) 576 require.NoError(t, err) 577 578 ethereumClient.On("PendingCodeAt", mock.Anything, mock.Anything).Return(uniswapSmartContractCodeRaw, nil) 579 580 _, err = bridgeClient.SwapUSDC(context.Background(), amount, amount) 581 require.NoError(t, err) 582 583 // 1. To address parameter. 584 to := common.HexToAddress(bridgeClient.UniswapAddress) 585 586 // 2. From address parameter. 587 from := common.HexToAddress(bridgeClient.EthereumAddress) 588 589 // 3. Swap amount parameter 590 swapAmount := big.NewInt(amount) 591 592 var rawAbi *abi.ABI 593 594 rawAbi, err = uniswapnetwork.UniswapMetaData.GetAbi() 595 require.NoError(t, err) 596 597 var pack []byte 598 599 pack, err = rawAbi.Pack("swapUSDCForZCNExactAmountOut", swapAmount, swapAmount) 600 require.NoError(t, err) 601 602 require.True(t, ethereumClient.AssertCalled( 603 t, 604 "EstimateGas", 605 context.Background(), 606 eth.CallMsg{ 607 To: &to, 608 From: from, 609 Data: pack, 610 Value: big.NewInt(0), 611 GasPrice: big.NewInt(400000), 612 }, 613 )) 614 }) 615 616 t.Run("should check configuration used by CreateSignedTransactionFromKeyStore", func(t *testing.T) { 617 bridgeClient.CreateSignedTransactionFromKeyStore(ethereumClient, 400000) 618 619 require.True(t, ethereumClient.AssertCalled( 620 t, 621 "PendingNonceAt", 622 context.Background(), 623 common.HexToAddress(ethereumAddress))) 624 625 require.True(t, keyStore.AssertCalled( 626 t, 627 "TimedUnlock", 628 accounts.Account{ 629 Address: common.HexToAddress(ethereumAddress), 630 }, 631 password, 632 time.Second*2, 633 )) 634 }) 635 636 t.Run("should check if gas price estimation works with correct alchemy ethereum node url", func(t *testing.T) { 637 bridgeClient = getBridgeClient(alchemyEthereumNodeURL, ethereumClient, transactionProvider, keyStore) 638 639 _, err := bridgeClient.EstimateGasPrice(context.Background()) 640 require.Contains(t, err.Error(), "Must be authenticated!") 641 }) 642 643 t.Run("should check if gas price estimation works with correct tenderly ethereum node url", func(t *testing.T) { 644 bridgeClient = getBridgeClient(tenderlyEthereumNodeURL, ethereumClient, transactionProvider, keyStore) 645 646 _, err := bridgeClient.EstimateGasPrice(context.Background()) 647 require.NoError(t, err) 648 }) 649 650 t.Run("should check if gas price estimation works with incorrect ethereum node url", func(t *testing.T) { 651 bridgeClient = getBridgeClient(infuraEthereumNodeURL, ethereumClient, transactionProvider, keyStore) 652 653 _, err := bridgeClient.EstimateGasPrice(context.Background()) 654 require.Error(t, err) 655 }) 656 }