code.vegaprotocol.io/vega@v0.79.0/cmd/vega/commands/bridge/erc20.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package bridge 17 18 import ( 19 "errors" 20 "fmt" 21 "sort" 22 "time" 23 24 "code.vegaprotocol.io/vega/core/bridges" 25 "code.vegaprotocol.io/vega/core/config" 26 "code.vegaprotocol.io/vega/core/nodewallets" 27 "code.vegaprotocol.io/vega/libs/num" 28 "code.vegaprotocol.io/vega/paths" 29 30 "github.com/jessevdk/go-flags" 31 ) 32 33 type ERC20Cmd struct { 34 config.VegaHomeFlag 35 config.PassphraseFlag 36 PrivateKey string `description:"A ethereum private key to be use to sign the messages" long:"private-key" required:"false"` 37 ChainID string `description:"The chain-id of the EVM bridge. Not required if generating signatures for the Ethereum bridge" long:"chain-id" required:"false"` 38 39 AddSigner ERC20AddSignerCmd `command:"add_signer" description:"Create signature to add a new signer to the erc20 bridge"` 40 RemoveSigner ERC20RemoveSignerCmd `command:"remove_signer" description:"Create signature to remove a signer from the erc20 bridge"` 41 SetThreshold ERC20SetThresholdCmd `command:"set_threshold" description:"Create signature to change the threshold of required signature to apply changes to the bridge"` 42 BurnNonce ERC20BurnNonceCmd `command:"burn_nonce" description:"Create signature to burn and existing nonce in order to prevent it to be used on the bridge"` 43 ListAsset ERC20ListAssetCmd `command:"list_asset" description:"Add a new erc20 asset to the erc20 bridge"` 44 VerifyListAsset ERC20VerifyListAssetCmd `command:"verify_list_asset" description:"Verify signatures to add a new erc20 asset to the erc20 bridge"` 45 RemoveAsset ERC20RemoveAssetCmd `command:"remove_asset" description:"Remove an erc20 asset from the erc20 bridge"` 46 WithdrawAsset ERC20WithdrawAssetCmd `command:"withdraw_asset" description:"Withdraw ERC20 from the bridge"` 47 VerifyWithdrawAsset ERC20VerifyWithdrawAssetCmd `command:"verify_withdraw_asset" description:"Verify withdraw ERC20 from the bridge"` 48 SetBridgeAddress ERC20SetBridgeAddressCmd `command:"set_bridge_address" description:"Update the bridge address use by the asset pool"` 49 SetMultisigControl ERC20SetMultisigControlCmd `command:"set_multisig_control" description:"Update the bridge address use by the asset pool"` 50 VerifyGlobalResume ERC20VerifyGlobalResumeCmd `command:"verify_global_resume" description:"Verify the signature to resume usage of the bridge"` 51 GlobalResume ERC20GlobalResumeCmd `command:"global_resume" description:"Build the signature to resume usage of the bridge"` 52 GlobalStop ERC20GlobalStopCmd `command:"global_stop" description:"Build the signature to stop the bridge"` 53 SetWithdrawDelay ERC20SetWithdrawDelayCmd `command:"set_withdraw_delay" description:"Update the withdraw delay for all asset"` 54 VerifySetWithdrawDelay ERC20VerifySetWithdrawDelayCmd `command:"verify_set_withdraw_delay" description:"Verify signatures to update the withdraw delay for all asset"` 55 SetAssetLimits ERC20SetAssetLimitsCmd `command:"set_asset_limits" description:"Update the limits for an asset"` 56 VerifySetAssetLimits ERC20VerifySetAssetLimitsCmd `command:"verify_set_asset_limits" description:"Verify signatures to update the limits for an asset"` 57 } 58 59 var erc20Cmd *ERC20Cmd 60 61 func (e *ERC20Cmd) GetSigner() (bridges.Signer, error) { 62 if len(e.PrivateKey) <= 0 { 63 pass, err := erc20Cmd.PassphraseFile.Get("node wallet", false) 64 if err != nil { 65 return nil, err 66 } 67 68 vegaPaths := paths.New(e.VegaHome) 69 70 if _, _, err := config.EnsureNodeConfig(vegaPaths); err != nil { 71 return nil, err 72 } 73 74 s, err := nodewallets.GetEthereumWallet(vegaPaths, pass) 75 if err != nil { 76 return nil, fmt.Errorf("couldn't get Ethereum node wallet: %w", err) 77 } 78 79 return s, nil 80 } 81 82 s, err := NewPrivKeySigner(e.PrivateKey) 83 if err != nil { 84 return nil, fmt.Errorf("couldn't load private key: %w", err) 85 } 86 87 return s, nil 88 } 89 90 func ERC20() *ERC20Cmd { 91 erc20Cmd = &ERC20Cmd{ 92 AddSigner: ERC20AddSignerCmd{}, 93 RemoveSigner: ERC20RemoveSignerCmd{}, 94 SetThreshold: ERC20SetThresholdCmd{}, 95 ListAsset: ERC20ListAssetCmd{}, 96 VerifyListAsset: ERC20VerifyListAssetCmd{}, 97 RemoveAsset: ERC20RemoveAssetCmd{}, 98 WithdrawAsset: ERC20WithdrawAssetCmd{}, 99 VerifyWithdrawAsset: ERC20VerifyWithdrawAssetCmd{}, 100 SetAssetLimits: ERC20SetAssetLimitsCmd{}, 101 VerifySetAssetLimits: ERC20VerifySetAssetLimitsCmd{}, 102 SetBridgeAddress: ERC20SetBridgeAddressCmd{}, 103 SetMultisigControl: ERC20SetMultisigControlCmd{}, 104 VerifyGlobalResume: ERC20VerifyGlobalResumeCmd{}, 105 GlobalResume: ERC20GlobalResumeCmd{}, 106 GlobalStop: ERC20GlobalStopCmd{}, 107 SetWithdrawDelay: ERC20SetWithdrawDelayCmd{}, 108 VerifySetWithdrawDelay: ERC20VerifySetWithdrawDelayCmd{}, 109 BurnNonce: ERC20BurnNonceCmd{}, 110 } 111 return erc20Cmd 112 } 113 114 type ERC20WithdrawAssetCmd struct { 115 TokenAddress string `description:"The Ethereum address of the new token" long:"token-address" required:"true"` 116 Amount string `description:"The amount to be withdrawn" long:"amount" required:"true"` 117 ReceiverAddress string `description:"The ethereum address of the wallet which is to receive the funds" long:"receiver-address" required:"true"` 118 BridgeAddress string `description:"The address of the vega bridge this transaction will be submitted to" long:"bridge-address" required:"true"` 119 Nonce string `description:"A nonce for this signature" long:"nonce" required:"true"` 120 Creation int64 `description:"creation time of the withdrawal (timestamp)" long:"creation" required:"true"` 121 } 122 123 func (opts *ERC20WithdrawAssetCmd) Execute(_ []string) error { 124 if _, err := flags.NewParser(opts, flags.Default|flags.IgnoreUnknown).Parse(); err != nil { 125 return err 126 } 127 128 w, err := erc20Cmd.GetSigner() 129 if err != nil { 130 return err 131 } 132 133 nonce, overflowed := num.UintFromString(opts.Nonce, 10) 134 if overflowed { 135 return errors.New("invalid nonce, needs to be base 10") 136 } 137 138 amount, overflowed := num.UintFromString(opts.Amount, 10) 139 if overflowed { 140 return errors.New("invalid amount, needs to be base 10") 141 } 142 143 creation := time.Unix(opts.Creation, 0) 144 145 erc20Logic := bridges.NewERC20Logic(w, opts.BridgeAddress, erc20Cmd.ChainID, erc20Cmd.ChainID == "") 146 bundle, err := erc20Logic.WithdrawAsset( 147 opts.TokenAddress, amount, opts.ReceiverAddress, creation, nonce, 148 ) 149 if err != nil { 150 return fmt.Errorf("unable to generate signature: %w", err) 151 } 152 153 fmt.Printf("0x%v\n", bundle.Signature.Hex()) 154 return nil 155 } 156 157 type ERC20VerifyWithdrawAssetCmd struct { 158 TokenAddress string `description:"The Ethereum address of the new token" long:"token-address" required:"true"` 159 Amount string `description:"The amount to be withdrawn" long:"amount" required:"true"` 160 ReceiverAddress string `description:"The ethereum address of the wallet which is to receive the funds" long:"receiver-address" required:"true"` 161 BridgeAddress string `description:"The address of the vega bridge this transaction will be submitted to" long:"bridge-address" required:"true"` 162 Nonce string `description:"A nonce for this signature" long:"nonce" required:"true"` 163 Creation int64 `description:"creation time of the withdrawal (timestamp)" long:"creation" required:"true"` 164 Signatures string `description:"signatures of the withdrawal" long:"signatures" required:"true"` 165 } 166 167 func (opts *ERC20VerifyWithdrawAssetCmd) Execute(_ []string) error { 168 if _, err := flags.NewParser(opts, flags.Default|flags.IgnoreUnknown).Parse(); err != nil { 169 return err 170 } 171 172 nonce, overflowed := num.UintFromString(opts.Nonce, 10) 173 if overflowed { 174 return errors.New("invalid nonce, needs to be base 10") 175 } 176 177 amount, overflowed := num.UintFromString(opts.Amount, 10) 178 if overflowed { 179 return errors.New("invalid amount, needs to be base 10") 180 } 181 182 creation := time.Unix(opts.Creation, 0) 183 184 if len(opts.Signatures) <= 0 { 185 return errors.New("missing signatures") 186 } 187 188 if (len(opts.Signatures)-2)%130 != 0 { 189 return errors.New("invalid signatures format") 190 } 191 192 erc20Logic := bridges.NewERC20Logic(nil, opts.BridgeAddress, erc20Cmd.ChainID, erc20Cmd.ChainID == "") 193 addresses, err := erc20Logic.VerifyWithdrawAsset( 194 opts.TokenAddress, amount, opts.ReceiverAddress, creation, nonce, opts.Signatures, 195 ) 196 if err != nil { 197 return fmt.Errorf("unable to generate signature: %w", err) 198 } 199 200 sort.Strings(addresses) 201 for _, v := range addresses { 202 fmt.Printf("%v\n", v) 203 } 204 return nil 205 } 206 207 type ERC20ListAssetCmd struct { 208 TokenAddress string `description:"The Ethereum address of the new token" long:"token-address" required:"true"` 209 VegaAssetID string `description:"The vega ID for this new token" long:"vega-asset-id" required:"true"` 210 BridgeAddress string `description:"The address of the vega bridge this transaction will be submitted to" long:"bridge-address" required:"true"` 211 Nonce string `description:"A nonce for this signature" long:"nonce" required:"true"` 212 LifetimeLimit string `description:"The lifetime deposit limit for the asset" long:"lifetime-limit" required:"true"` 213 WithdrawThreshold string `description:"The withdrawal threshold for this asset" long:"withdraw-threshold" required:"true"` 214 } 215 216 func (opts *ERC20ListAssetCmd) Execute(_ []string) error { 217 if _, err := flags.NewParser(opts, flags.Default|flags.IgnoreUnknown).Parse(); err != nil { 218 return err 219 } 220 221 w, err := erc20Cmd.GetSigner() 222 if err != nil { 223 return err 224 } 225 226 nonce, overflowed := num.UintFromString(opts.Nonce, 10) 227 if overflowed { 228 return errors.New("invalid nonce, needs to be base 10") 229 } 230 lifetimeLimit, overflowed := num.UintFromString(opts.LifetimeLimit, 10) 231 if overflowed { 232 return errors.New("invalid lifetime-limit, needs to be base 10") 233 } 234 withdrawThreshod, overflowed := num.UintFromString(opts.WithdrawThreshold, 10) 235 if overflowed { 236 return errors.New("invalid withdraw-threshold, needs to be base 10") 237 } 238 239 erc20Logic := bridges.NewERC20Logic(w, opts.BridgeAddress, erc20Cmd.ChainID, erc20Cmd.ChainID == "") 240 bundle, err := erc20Logic.ListAsset( 241 opts.TokenAddress, opts.VegaAssetID, lifetimeLimit, withdrawThreshod, nonce, 242 ) 243 if err != nil { 244 return fmt.Errorf("unable to generate signature: %w", err) 245 } 246 247 fmt.Printf("0x%v\n", bundle.Signature.Hex()) 248 return nil 249 } 250 251 type ERC20VerifyListAssetCmd struct { 252 TokenAddress string `description:"The Ethereum address of the new token" long:"token-address" required:"true"` 253 VegaAssetID string `description:"The vega ID for this new token" long:"vega-asset-id" required:"true"` 254 BridgeAddress string `description:"The address of the vega bridge this transaction will be submitted to" long:"bridge-address" required:"true"` 255 Nonce string `description:"A nonce for this signature" long:"nonce" required:"true"` 256 LifetimeLimit string `description:"The lifetime deposit limit for the asset" long:"lifetime-limit" required:"true"` 257 WithdrawThreshold string `description:"The withdrawal threshold for this asset" long:"withdraw-threshold" required:"true"` 258 Signatures string `description:"The signature bundle to verify" long:"signatures" required:"true"` 259 } 260 261 func (opts *ERC20VerifyListAssetCmd) Execute(_ []string) error { 262 if _, err := flags.NewParser(opts, flags.Default|flags.IgnoreUnknown).Parse(); err != nil { 263 return err 264 } 265 266 nonce, overflowed := num.UintFromString(opts.Nonce, 10) 267 if overflowed { 268 return errors.New("invalid nonce, needs to be base 10") 269 } 270 lifetimeLimit, overflowed := num.UintFromString(opts.LifetimeLimit, 10) 271 if overflowed { 272 return errors.New("invalid lifetime-limit, needs to be base 10") 273 } 274 withdrawThreshod, overflowed := num.UintFromString(opts.WithdrawThreshold, 10) 275 if overflowed { 276 return errors.New("invalid withdraw-threshold, needs to be base 10") 277 } 278 279 if len(opts.Signatures) <= 0 { 280 return errors.New("missing signatures") 281 } 282 283 if (len(opts.Signatures)-2)%130 != 0 { 284 return errors.New("invalid signatures format") 285 } 286 287 erc20Logic := bridges.NewERC20Logic(nil, opts.BridgeAddress, erc20Cmd.ChainID, erc20Cmd.ChainID == "") 288 addresses, err := erc20Logic.VerifyListAsset( 289 opts.TokenAddress, opts.VegaAssetID, lifetimeLimit, withdrawThreshod, nonce, opts.Signatures, 290 ) 291 if err != nil { 292 return fmt.Errorf("unable to generate signature: %w", err) 293 } 294 295 sort.Strings(addresses) 296 for _, v := range addresses { 297 fmt.Printf("%v\n", v) 298 } 299 return nil 300 } 301 302 type ERC20RemoveAssetCmd struct { 303 TokenAddress string `description:"The Ethereum address of the new token" long:"token-address" required:"true"` 304 BridgeAddress string `description:"The address of the vega bridge this transaction will be submitted to" long:"bridge-address" required:"true"` 305 Nonce string `description:"A nonce for this signature" long:"nonce" required:"true"` 306 } 307 308 func (opts *ERC20RemoveAssetCmd) Execute(_ []string) error { 309 if _, err := flags.NewParser(opts, flags.Default|flags.IgnoreUnknown).Parse(); err != nil { 310 return err 311 } 312 313 w, err := erc20Cmd.GetSigner() 314 if err != nil { 315 return err 316 } 317 318 nonce, overflowed := num.UintFromString(opts.Nonce, 10) 319 if overflowed { 320 return errors.New("invalid nonce, needs to be base 10") 321 } 322 323 erc20Logic := bridges.NewERC20Logic(w, opts.BridgeAddress, erc20Cmd.ChainID, erc20Cmd.ChainID == "") 324 bundle, err := erc20Logic.RemoveAsset( 325 opts.TokenAddress, nonce, 326 ) 327 if err != nil { 328 return fmt.Errorf("unable to generate signature: %w", err) 329 } 330 331 fmt.Printf("0x%v\n", bundle.Signature.Hex()) 332 return nil 333 } 334 335 type ERC20AddSignerCmd struct { 336 NewSigner string `description:"Ethereum address of the new signer" long:"new-signer" required:"true"` 337 Submitter string `description:"Ethereum address of the submitter of the transaction" long:"submitter" required:"true"` 338 Nonce string `description:"A nonce for this signature" long:"nonce" required:"true"` 339 } 340 341 func (opts *ERC20AddSignerCmd) Execute(_ []string) error { 342 if _, err := flags.NewParser(opts, flags.Default|flags.IgnoreUnknown).Parse(); err != nil { 343 return err 344 } 345 346 w, err := erc20Cmd.GetSigner() 347 if err != nil { 348 return err 349 } 350 351 nonce, overflowed := num.UintFromString(opts.Nonce, 10) 352 if overflowed { 353 return errors.New("invalid nonce, needs to be base 10") 354 } 355 356 multiSigControl := bridges.NewERC20MultiSigControl(w, erc20Cmd.ChainID, erc20Cmd.ChainID == "") 357 bundle, err := multiSigControl.AddSigner( 358 opts.NewSigner, opts.Submitter, nonce, 359 ) 360 if err != nil { 361 return fmt.Errorf("unable to generate signature: %w", err) 362 } 363 364 fmt.Printf("0x%v\n", bundle.Signature.Hex()) 365 return nil 366 } 367 368 type ERC20RemoveSignerCmd struct { 369 OldSigner string `description:"Ethereum address of signer to remove" long:"old-signer" required:"true"` 370 Submitter string `description:"Ethereum address of the submitter of the transaction" long:"submitter" required:"true"` 371 Nonce string `description:"A nonce for this signature" long:"nonce" required:"true"` 372 } 373 374 func (opts *ERC20RemoveSignerCmd) Execute(_ []string) error { 375 if _, err := flags.NewParser(opts, flags.Default|flags.IgnoreUnknown).Parse(); err != nil { 376 return err 377 } 378 379 w, err := erc20Cmd.GetSigner() 380 if err != nil { 381 return err 382 } 383 384 nonce, overflowed := num.UintFromString(opts.Nonce, 10) 385 if overflowed { 386 return errors.New("invalid nonce, needs to be base 10") 387 } 388 389 multiSigControl := bridges.NewERC20MultiSigControl(w, erc20Cmd.ChainID, erc20Cmd.ChainID == "") 390 bundle, err := multiSigControl.RemoveSigner( 391 opts.OldSigner, opts.Submitter, nonce, 392 ) 393 if err != nil { 394 return fmt.Errorf("unable to generate signature: %w", err) 395 } 396 397 fmt.Printf("0x%v\n", bundle.Signature.Hex()) 398 return nil 399 } 400 401 type ERC20SetThresholdCmd struct { 402 NewThreshold uint16 `description:"The new threshold to be used on the bridge" long:"new-threshold" required:"true"` 403 Submitter string `description:"Ethereum address of the submitter of the transaction" long:"submitter" required:"true"` 404 Nonce string `description:"A nonce for this signature" long:"nonce" required:"true"` 405 } 406 407 func (opts *ERC20SetThresholdCmd) Execute(_ []string) error { 408 if _, err := flags.NewParser(opts, flags.Default|flags.IgnoreUnknown).Parse(); err != nil { 409 return err 410 } 411 412 w, err := erc20Cmd.GetSigner() 413 if err != nil { 414 return err 415 } 416 417 if opts.NewThreshold == 0 || opts.NewThreshold > 1000 { 418 return fmt.Errorf("invalid new threshold, required to be > 0 and <= 1000, got %d", opts.NewThreshold) 419 } 420 421 nonce, overflowed := num.UintFromString(opts.Nonce, 10) 422 if overflowed { 423 return errors.New("invalid nonce, needs to be base 10 and not overflow") 424 } 425 426 multiSigControl := bridges.NewERC20MultiSigControl(w, erc20Cmd.ChainID, erc20Cmd.ChainID == "") 427 bundle, err := multiSigControl.SetThreshold( 428 opts.NewThreshold, opts.Submitter, nonce, 429 ) 430 if err != nil { 431 return fmt.Errorf("unable to generate signature: %w", err) 432 } 433 434 fmt.Printf("0x%v\n", bundle.Signature.Hex()) 435 return nil 436 } 437 438 type ERC20BurnNonceCmd struct { 439 Submitter string `description:"Ethereum address of the submitter of the transaction" long:"submitter" required:"true"` 440 Nonce string `description:"A nonce for this signature" long:"nonce" required:"true"` 441 } 442 443 func (opts *ERC20BurnNonceCmd) Execute(_ []string) error { 444 if _, err := flags.NewParser(opts, flags.Default|flags.IgnoreUnknown).Parse(); err != nil { 445 return err 446 } 447 448 w, err := erc20Cmd.GetSigner() 449 if err != nil { 450 return err 451 } 452 453 nonce, overflowed := num.UintFromString(opts.Nonce, 10) 454 if overflowed { 455 return errors.New("invalid nonce, needs to be base 10 and not overflow") 456 } 457 458 multiSigControl := bridges.NewERC20MultiSigControl(w, erc20Cmd.ChainID, erc20Cmd.ChainID == "") 459 bundle, err := multiSigControl.BurnNonce(opts.Submitter, nonce) 460 if err != nil { 461 return fmt.Errorf("unable to generate signature: %w", err) 462 } 463 464 fmt.Printf("0x%v\n", bundle.Signature.Hex()) 465 return nil 466 } 467 468 type ERC20SetBridgeAddressCmd struct { 469 NewAddress string `description:"The Ethereum address of the bridge" long:"new-address" required:"true"` 470 AssetPoolAddress string `description:"The address of the vega asset pool this transaction will be submitted to" long:"asset-pool-address" required:"true"` 471 Nonce string `description:"A nonce for this signature" long:"nonce" required:"true"` 472 } 473 474 func (opts *ERC20SetBridgeAddressCmd) Execute(_ []string) error { 475 if _, err := flags.NewParser(opts, flags.Default|flags.IgnoreUnknown).Parse(); err != nil { 476 return err 477 } 478 479 w, err := erc20Cmd.GetSigner() 480 if err != nil { 481 return err 482 } 483 484 nonce, overflowed := num.UintFromString(opts.Nonce, 10) 485 if overflowed { 486 return errors.New("invalid nonce, needs to be base 10") 487 } 488 489 erc20Logic := bridges.NewERC20AssetPool(w, opts.AssetPoolAddress, erc20Cmd.ChainID, erc20Cmd.ChainID == "") 490 bundle, err := erc20Logic.SetBridgeAddress( 491 opts.NewAddress, nonce, 492 ) 493 if err != nil { 494 return fmt.Errorf("unable to generate signature: %w", err) 495 } 496 497 fmt.Printf("0x%v\n", bundle.Signature.Hex()) 498 return nil 499 } 500 501 type ERC20SetMultisigControlCmd struct { 502 NewAddress string `description:"The Ethereum address of the bridge" long:"new-address" required:"true"` 503 AssetPoolAddress string `description:"The address of the vega asset pool this transaction will be submitted to" long:"asset-pool-address" required:"true"` 504 Nonce string `description:"A nonce for this signature" long:"nonce" required:"true"` 505 } 506 507 func (opts *ERC20SetMultisigControlCmd) Execute(_ []string) error { 508 if _, err := flags.NewParser(opts, flags.Default|flags.IgnoreUnknown).Parse(); err != nil { 509 return err 510 } 511 512 w, err := erc20Cmd.GetSigner() 513 if err != nil { 514 return err 515 } 516 517 nonce, overflowed := num.UintFromString(opts.Nonce, 10) 518 if overflowed { 519 return errors.New("invalid nonce, needs to be base 10") 520 } 521 522 erc20Logic := bridges.NewERC20AssetPool(w, opts.AssetPoolAddress, erc20Cmd.ChainID, erc20Cmd.ChainID == "") 523 bundle, err := erc20Logic.SetMultiSigControl( 524 opts.NewAddress, nonce, 525 ) 526 if err != nil { 527 return fmt.Errorf("unable to generate signature: %w", err) 528 } 529 530 fmt.Printf("0x%v\n", bundle.Signature.Hex()) 531 return nil 532 } 533 534 type ERC20GlobalStopCmd struct { 535 Nonce string `description:"A nonce for this signature" long:"nonce" required:"true"` 536 BridgeAddress string `description:"The address of the vega bridge this transaction will be submitted to" long:"bridge-address" required:"true"` 537 } 538 539 func (opts *ERC20GlobalStopCmd) Execute(_ []string) error { 540 if _, err := flags.NewParser(opts, flags.Default|flags.IgnoreUnknown).Parse(); err != nil { 541 return err 542 } 543 544 w, err := erc20Cmd.GetSigner() 545 if err != nil { 546 return err 547 } 548 549 nonce, overflowed := num.UintFromString(opts.Nonce, 10) 550 if overflowed { 551 return errors.New("invalid nonce, needs to be base 10 and not overflow") 552 } 553 554 erc20 := bridges.NewERC20Logic(w, opts.BridgeAddress, erc20Cmd.ChainID, erc20Cmd.ChainID == "") 555 bundle, err := erc20.GlobalStop( 556 nonce, 557 ) 558 if err != nil { 559 return fmt.Errorf("unable to generate signature: %w", err) 560 } 561 562 fmt.Printf("0x%v\n", bundle.Signature.Hex()) 563 return nil 564 } 565 566 type ERC20GlobalResumeCmd struct { 567 Nonce string `description:"A nonce for this signature" long:"nonce" required:"true"` 568 BridgeAddress string `description:"The address of the vega bridge this transaction will be submitted to" long:"bridge-address" required:"true"` 569 } 570 571 func (opts *ERC20GlobalResumeCmd) Execute(_ []string) error { 572 if _, err := flags.NewParser(opts, flags.Default|flags.IgnoreUnknown).Parse(); err != nil { 573 return err 574 } 575 576 w, err := erc20Cmd.GetSigner() 577 if err != nil { 578 return err 579 } 580 581 nonce, overflowed := num.UintFromString(opts.Nonce, 10) 582 if overflowed { 583 return errors.New("invalid nonce, needs to be base 10 and not overflow") 584 } 585 586 erc20 := bridges.NewERC20Logic(w, opts.BridgeAddress, erc20Cmd.ChainID, erc20Cmd.ChainID == "") 587 bundle, err := erc20.GlobalResume( 588 nonce, 589 ) 590 if err != nil { 591 return fmt.Errorf("unable to generate signature: %w", err) 592 } 593 594 fmt.Printf("0x%v\n", bundle.Signature.Hex()) 595 return nil 596 } 597 598 type ERC20VerifyGlobalResumeCmd struct { 599 Nonce string `description:"A nonce for this signature" long:"nonce" required:"true"` 600 BridgeAddress string `description:"The address of the vega bridge this transaction will be submitted to" long:"bridge-address" required:"true"` 601 Signatures string `description:"The list of signatures from the validators" long:"signatures" required:"true"` 602 } 603 604 func (opts *ERC20VerifyGlobalResumeCmd) Execute(_ []string) error { 605 if _, err := flags.NewParser(opts, flags.Default|flags.IgnoreUnknown).Parse(); err != nil { 606 return err 607 } 608 609 nonce, overflowed := num.UintFromString(opts.Nonce, 10) 610 if overflowed { 611 return errors.New("invalid nonce, needs to be base 10 and not overflow") 612 } 613 614 if len(opts.Signatures) <= 0 { 615 return errors.New("missing signatures") 616 } 617 618 if (len(opts.Signatures)-2)%130 != 0 { 619 return errors.New("invalid signatures format") 620 } 621 622 erc20 := bridges.NewERC20Logic(nil, opts.BridgeAddress, erc20Cmd.ChainID, erc20Cmd.ChainID == "") 623 signers, err := erc20.VerifyGlobalResume( 624 nonce, opts.Signatures, 625 ) 626 if err != nil { 627 return fmt.Errorf("unable to generate signature: %w", err) 628 } 629 630 sort.Strings(signers) 631 for _, v := range signers { 632 fmt.Printf("%v\n", v) 633 } 634 return nil 635 } 636 637 type ERC20SetAssetLimitsCmd struct { 638 WithdrawThreshold string `description:"The threshold" long:"withdraw-threshold" required:"true"` 639 DepositLifetimeMaximum string `description:"The maxium deposit allowed per address" long:"deposit-lifetime-maximum" required:"true"` 640 Nonce string `description:"A nonce for this signature" long:"nonce" required:"true"` 641 BridgeAddress string `description:"The address of the vega bridge this transaction will be submitted to" long:"bridge-address" required:"true"` 642 TokenAddress string `description:"The address of the token to be used" long:"token-address" required:"true"` 643 } 644 645 func (opts *ERC20SetAssetLimitsCmd) Execute(_ []string) error { 646 if _, err := flags.NewParser(opts, flags.Default|flags.IgnoreUnknown).Parse(); err != nil { 647 return err 648 } 649 650 w, err := erc20Cmd.GetSigner() 651 if err != nil { 652 return err 653 } 654 655 nonce, overflowed := num.UintFromString(opts.Nonce, 10) 656 if overflowed { 657 return errors.New("invalid nonce, needs to be base 10 and not overflow") 658 } 659 660 threshold, overflowed := num.UintFromString(opts.WithdrawThreshold, 10) 661 if overflowed { 662 return errors.New("invalid withdraw-threshold, needs to be base 10 and not overflow") 663 } 664 665 depositLifetime, overflowed := num.UintFromString(opts.DepositLifetimeMaximum, 10) 666 if overflowed { 667 return errors.New("invalid deposit-lifetime-maximum needs to be base 10 and not overflow") 668 } 669 670 erc20 := bridges.NewERC20Logic(w, opts.BridgeAddress, erc20Cmd.ChainID, erc20Cmd.ChainID == "") 671 bundle, err := erc20.SetAssetLimits( 672 opts.TokenAddress, depositLifetime, threshold, nonce, 673 ) 674 if err != nil { 675 return fmt.Errorf("unable to generate signature: %w", err) 676 } 677 678 fmt.Printf("0x%v\n", bundle.Signature.Hex()) 679 return nil 680 } 681 682 type ERC20VerifySetAssetLimitsCmd struct { 683 WithdrawThreshold string `description:"The threshold" long:"withdraw-threshold" required:"true"` 684 DepositLifetimeMaximum string `description:"The maxium deposit allowed per address" long:"deposit-lifetime-maximum" required:"true"` 685 Nonce string `description:"A nonce for this signature" long:"nonce" required:"true"` 686 BridgeAddress string `description:"The address of the vega bridge this transaction will be submitted to" long:"bridge-address" required:"true"` 687 TokenAddress string `description:"The address of the token to be used" long:"token-address" required:"true"` 688 Signatures string `description:"The list of signatures from the validators" long:"signatures" required:"true"` 689 } 690 691 func (opts *ERC20VerifySetAssetLimitsCmd) Execute(_ []string) error { 692 if _, err := flags.NewParser(opts, flags.Default|flags.IgnoreUnknown).Parse(); err != nil { 693 return err 694 } 695 696 nonce, overflowed := num.UintFromString(opts.Nonce, 10) 697 if overflowed { 698 return errors.New("invalid nonce, needs to be base 10 and not overflow") 699 } 700 701 threshold, overflowed := num.UintFromString(opts.WithdrawThreshold, 10) 702 if overflowed { 703 return errors.New("invalid withdraw-threshold, needs to be base 10 and not overflow") 704 } 705 706 depositLifetime, overflowed := num.UintFromString(opts.DepositLifetimeMaximum, 10) 707 if overflowed { 708 return errors.New("invalid deposit-lifetime-maximum needs to be base 10 and not overflow") 709 } 710 711 if len(opts.Signatures) <= 0 { 712 return errors.New("missing signatures") 713 } 714 715 if (len(opts.Signatures)-2)%130 != 0 { 716 return errors.New("invalid signatures format") 717 } 718 719 erc20 := bridges.NewERC20Logic(nil, opts.BridgeAddress, erc20Cmd.ChainID, erc20Cmd.ChainID == "") 720 signers, err := erc20.VerifySetAssetLimits( 721 opts.TokenAddress, depositLifetime, threshold, nonce, opts.Signatures, 722 ) 723 if err != nil { 724 return fmt.Errorf("unable to generate signature: %w", err) 725 } 726 727 sort.Strings(signers) 728 for _, v := range signers { 729 fmt.Printf("%v\n", v) 730 } 731 return nil 732 } 733 734 type ERC20SetWithdrawDelayCmd struct { 735 Delay time.Duration `description:"The delay to be applied to all withdrawals" long:"delay" required:"true"` 736 Nonce string `description:"A nonce for this signature" long:"nonce" required:"true"` 737 BridgeAddress string `description:"The address of the vega bridge this transaction will be submitted to" long:"bridge-address" required:"true"` 738 } 739 740 func (opts *ERC20SetWithdrawDelayCmd) Execute(_ []string) error { 741 if _, err := flags.NewParser(opts, flags.Default|flags.IgnoreUnknown).Parse(); err != nil { 742 return err 743 } 744 745 w, err := erc20Cmd.GetSigner() 746 if err != nil { 747 return err 748 } 749 750 nonce, overflowed := num.UintFromString(opts.Nonce, 10) 751 if overflowed { 752 return errors.New("invalid nonce, needs to be base 10 and not overflow") 753 } 754 755 erc20 := bridges.NewERC20Logic(w, opts.BridgeAddress, erc20Cmd.ChainID, erc20Cmd.ChainID == "") 756 bundle, err := erc20.SetWithdrawDelay( 757 opts.Delay, nonce, 758 ) 759 if err != nil { 760 return fmt.Errorf("unable to generate signature: %w", err) 761 } 762 763 fmt.Printf("0x%v\n", bundle.Signature.Hex()) 764 return nil 765 } 766 767 type ERC20VerifySetWithdrawDelayCmd struct { 768 Delay time.Duration `description:"The delay to be applied to all withdrawals" long:"delay" required:"true"` 769 Nonce string `description:"A nonce for this signature" long:"nonce" required:"true"` 770 BridgeAddress string `description:"The address of the vega bridge this transaction will be submitted to" long:"bridge-address" required:"true"` 771 Signatures string `description:"The signature bundle to verify" long:"signatures" required:"true"` 772 } 773 774 func (opts *ERC20VerifySetWithdrawDelayCmd) Execute(_ []string) error { 775 if _, err := flags.NewParser(opts, flags.Default|flags.IgnoreUnknown).Parse(); err != nil { 776 return err 777 } 778 779 nonce, overflowed := num.UintFromString(opts.Nonce, 10) 780 if overflowed { 781 return errors.New("invalid nonce, needs to be base 10 and not overflow") 782 } 783 784 if len(opts.Signatures) <= 0 { 785 return errors.New("missing signatures") 786 } 787 788 if (len(opts.Signatures)-2)%130 != 0 { 789 return errors.New("invalid signatures format") 790 } 791 792 erc20Logic := bridges.NewERC20Logic(nil, opts.BridgeAddress, erc20Cmd.ChainID, erc20Cmd.ChainID == "") 793 addresses, err := erc20Logic.VerifyWithdrawDelay( 794 opts.Delay, nonce, opts.Signatures, 795 ) 796 if err != nil { 797 return fmt.Errorf("unable to generate signature: %w", err) 798 } 799 800 sort.Strings(addresses) 801 for _, v := range addresses { 802 fmt.Printf("%v\n", v) 803 } 804 return nil 805 }