From 81d53e11b1783be83648f2009c074465c54e165a Mon Sep 17 00:00:00 2001 From: Xavier Romero Date: Mon, 9 Dec 2024 10:17:19 +0100 Subject: [PATCH 1/4] Add cmd to wrap deployed bytecode --- README.md | 2 + cmd/retest/retest.go | 18 +-------- cmd/root.go | 2 + cmd/wrapcontract/usage.md | 18 +++++++++ cmd/wrapcontract/wrapcontract.go | 33 ++++++++++++++++ doc/polycli.md | 2 + doc/polycli_wrap-contract.md | 64 ++++++++++++++++++++++++++++++++ util/util.go | 20 ++++++++++ 8 files changed, 143 insertions(+), 16 deletions(-) create mode 100644 cmd/wrapcontract/usage.md create mode 100644 cmd/wrapcontract/wrapcontract.go create mode 100644 doc/polycli_wrap-contract.md diff --git a/README.md b/README.md index 5601ca53..35f8bf6b 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,8 @@ Note: Do not modify this section! It is auto-generated by `cobra` using `make ge - [polycli wallet](doc/polycli_wallet.md) - Create or inspect BIP39(ish) wallets. +- [polycli wrap-contract](doc/polycli_wrap-contract.md) - Wrap deployed bytecode into create bytecode. + ## Testing diff --git a/cmd/retest/retest.go b/cmd/retest/retest.go index d7c452d2..73b1a94f 100644 --- a/cmd/retest/retest.go +++ b/cmd/retest/retest.go @@ -11,6 +11,7 @@ import ( "github.com/0xPolygon/polygon-cli/abi" "github.com/rs/zerolog/log" "github.com/spf13/cobra" + "github.com/0xPolygon/polygon-cli/util" "io" "math" "math/big" @@ -657,26 +658,11 @@ func processRawStringToString(data string) string { func WrapPredeployedCode(pre EthTestPre) string { rawCode := WrappedData{raw: pre.Code} deployedCode := rawCode.ToString() - deployedCode = strings.TrimPrefix(deployedCode, "0x") storageInitCode := storageToByteCode(pre.Storage) - codeCopySize := len(deployedCode) / 2 - codeCopyOffset := (len(storageInitCode) / 2) + 13 + 8 // 13 for CODECOPY + 8 for RETURN - - return fmt.Sprintf( - "0x%s"+ // storage initialization code - "63%08x"+ // PUSH4 to indicate the size of the data that should be copied into memory - "63%08x"+ // PUSH4 to indicate the offset in the call data to start the copy - "6000"+ // PUSH1 00 to indicate the destination offset in memory - "39"+ // CODECOPY - "63%08x"+ // PUSH4 to indicate the size of the data to be returned from memory - "6000"+ // PUSH1 00 to indicate that it starts from offset 0 - "F3"+ // RETURN - "%s", // CODE starts here. - storageInitCode, codeCopySize, codeCopyOffset, codeCopySize, deployedCode) + return util.WrapDeployedCode(deployedCode, storageInitCode) } - // storageToByteCode func storageToByteCode(storage map[string]EthTestNumeric) string { if len(storage) == 0 { diff --git a/cmd/root.go b/cmd/root.go index e4240f26..4b794202 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -30,6 +30,7 @@ import ( "github.com/0xPolygon/polygon-cli/cmd/signer" "github.com/0xPolygon/polygon-cli/cmd/version" "github.com/0xPolygon/polygon-cli/cmd/wallet" + "github.com/0xPolygon/polygon-cli/cmd/wrapcontract" ) var ( @@ -128,6 +129,7 @@ func NewPolycliCommand() *cobra.Command { ulxly.ULxLyCmd, version.VersionCmd, wallet.WalletCmd, + wrapcontract.WrapContractCmd, ) return cmd } diff --git a/cmd/wrapcontract/usage.md b/cmd/wrapcontract/usage.md new file mode 100644 index 00000000..03e5c98d --- /dev/null +++ b/cmd/wrapcontract/usage.md @@ -0,0 +1,18 @@ +This command takes the bytecode that we want to be deployed for a new contract, and wraps its into the bytecode that we can use to create the contract. + +```bash +$ polycli wrap-contract 69602a60005260206000f3600052600a6016f3 + +``` + +The resulting bytecode will be formatted this way: + + 0x?? // storage initialization code if any + 63?? // PUSH4 to indicate the size of the data that should be copied into memory + 63?? // PUSH4 to indicate the offset in the call data to start the copy + 6000 // PUSH1 00 to indicate the destination offset in memory + 39 // CODECOPY + 63?? // PUSH4 to indicate the size of the data to be returned from memory + 6000 // PUSH1 00 to indicate that it starts from offset 0 + F3 // RETURN + ??, // Deployed Bytecode diff --git a/cmd/wrapcontract/wrapcontract.go b/cmd/wrapcontract/wrapcontract.go new file mode 100644 index 00000000..101ea25b --- /dev/null +++ b/cmd/wrapcontract/wrapcontract.go @@ -0,0 +1,33 @@ +package wrapcontract + +import ( + "fmt" + _ "embed" + "github.com/spf13/cobra" + "github.com/0xPolygon/polygon-cli/util" +) + +var ( + //go:embed usage.md + usage string +) + +var WrapContractCmd = &cobra.Command{ + Use: "wrap-contract bytecode", + Aliases: []string{"wrapcontract", "wrapContract"}, + Short: "Wrap deployed bytecode into create bytecode.", + Long: usage, + RunE: func(cmd *cobra.Command, args []string) error { + deployed_bytecode := args[0] + storage_bytecode := "" + create_bytecode := util.WrapDeployedCode(deployed_bytecode, storage_bytecode) + fmt.Println(create_bytecode) + return nil + }, + Args: func(cmd *cobra.Command, args []string) error { + if len(args) != 1 { + return fmt.Errorf("expected exactly one argument: bytecode") + } + return nil + }, +} diff --git a/doc/polycli.md b/doc/polycli.md index c8d69f34..b0b91213 100644 --- a/doc/polycli.md +++ b/doc/polycli.md @@ -77,3 +77,5 @@ Polycli is a collection of tools that are meant to be useful while building, tes - [polycli wallet](polycli_wallet.md) - Create or inspect BIP39(ish) wallets. +- [polycli wrap-contract](polycli_wrap-contract.md) - Wrap deployed bytecode into create bytecode. + diff --git a/doc/polycli_wrap-contract.md b/doc/polycli_wrap-contract.md new file mode 100644 index 00000000..d7ae6be3 --- /dev/null +++ b/doc/polycli_wrap-contract.md @@ -0,0 +1,64 @@ +# `polycli wrap-contract` + +> Auto-generated documentation. + +## Table of Contents + +- [Description](#description) +- [Usage](#usage) +- [Flags](#flags) +- [See Also](#see-also) + +## Description + +Wrap deployed bytecode into create bytecode. + +```bash +polycli wrap-contract bytecode [flags] +``` + +## Usage + +This command takes the bytecode that we want to be deployed for a new contract, and wraps its into the bytecode that we can use to create the contract. + +```bash +$ polycli wrap-contract 69602a60005260206000f3600052600a6016f3 + +``` + +The resulting bytecode will be formatted this way: + + 0x?? // storage initialization code if any + 63?? // PUSH4 to indicate the size of the data that should be copied into memory + 63?? // PUSH4 to indicate the offset in the call data to start the copy + 6000 // PUSH1 00 to indicate the destination offset in memory + 39 // CODECOPY + 63?? // PUSH4 to indicate the size of the data to be returned from memory + 6000 // PUSH1 00 to indicate that it starts from offset 0 + F3 // RETURN + ??, // Deployed Bytecode + +## Flags + +```bash + -h, --help help for wrap-contract +``` + +The command also inherits flags from parent commands. + +```bash + --config string config file (default is $HOME/.polygon-cli.yaml) + --pretty-logs Should logs be in pretty format or JSON (default true) + -v, --verbosity int 0 - Silent + 100 Panic + 200 Fatal + 300 Error + 400 Warning + 500 Info + 600 Debug + 700 Trace (default 500) +``` + +## See also + +- [polycli](polycli.md) - A Swiss Army knife of blockchain tools. diff --git a/util/util.go b/util/util.go index a6f533ac..574e47a1 100644 --- a/util/util.go +++ b/util/util.go @@ -317,3 +317,23 @@ func BlockUntilSuccessful(ctx context.Context, c *ethclient.Client, retryable fu b := backoff.WithContext(backoff.WithMaxRetries(backoff.NewConstantBackOff(5*time.Second), 24), ctx) return backoff.Retry(retryable, b) } + +func WrapDeployedCode(deployedBytecode string, storageBytecode string) string { + deployedBytecode = strings.TrimPrefix(deployedBytecode, "0x") + storageBytecode = strings.TrimPrefix(storageBytecode, "0x") + + codeCopySize := len(deployedBytecode) / 2 + codeCopyOffset := (len(storageBytecode)/2) + 13 + 8 // 13 for CODECOPY + 8 for RETURN + + return fmt.Sprintf( + "0x%s"+ // storage initialization code + "63%08x"+ // PUSH4 to indicate the size of the data that should be copied into memory + "63%08x"+ // PUSH4 to indicate the offset in the call data to start the copy + "6000"+ // PUSH1 00 to indicate the destination offset in memory + "39"+ // CODECOPY + "63%08x"+ // PUSH4 to indicate the size of the data to be returned from memory + "6000"+ // PUSH1 00 to indicate that it starts from offset 0 + "F3"+ // RETURN + "%s", // CODE starts here. + storageBytecode, codeCopySize, codeCopyOffset, codeCopySize, deployedBytecode) +} From 871fd4188fc7c5c8db95b191a4d1f387c2de2a08 Mon Sep 17 00:00:00 2001 From: Xavier Romero <47888584+xavier-romero@users.noreply.github.com> Date: Tue, 10 Dec 2024 12:06:23 +0100 Subject: [PATCH 2/4] Update cmd/wrapcontract/usage.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Léo Vincent <28714795+leovct@users.noreply.github.com> --- cmd/wrapcontract/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/wrapcontract/usage.md b/cmd/wrapcontract/usage.md index 03e5c98d..789dd74c 100644 --- a/cmd/wrapcontract/usage.md +++ b/cmd/wrapcontract/usage.md @@ -1,4 +1,4 @@ -This command takes the bytecode that we want to be deployed for a new contract, and wraps its into the bytecode that we can use to create the contract. +This command takes the runtime bytecode, the bytecode deployed on-chain, as input and converts it into creation bytecode, the bytecode used to create the contract ```bash $ polycli wrap-contract 69602a60005260206000f3600052600a6016f3 From 072a19057a0b9e8479e1b600bb75d13d7112e412 Mon Sep 17 00:00:00 2001 From: Xavier Romero <47888584+xavier-romero@users.noreply.github.com> Date: Tue, 10 Dec 2024 12:06:38 +0100 Subject: [PATCH 3/4] Update util/util.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Léo Vincent <28714795+leovct@users.noreply.github.com> --- util/util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/util.go b/util/util.go index 574e47a1..9927871f 100644 --- a/util/util.go +++ b/util/util.go @@ -333,7 +333,7 @@ func WrapDeployedCode(deployedBytecode string, storageBytecode string) string { "39"+ // CODECOPY "63%08x"+ // PUSH4 to indicate the size of the data to be returned from memory "6000"+ // PUSH1 00 to indicate that it starts from offset 0 - "F3"+ // RETURN + "f3"+ // RETURN "%s", // CODE starts here. storageBytecode, codeCopySize, codeCopyOffset, codeCopySize, deployedBytecode) } From 893509c8f2585635ec39a1f06435f0ece73cc5fa Mon Sep 17 00:00:00 2001 From: Xavier Romero Date: Tue, 10 Dec 2024 12:09:05 +0100 Subject: [PATCH 4/4] ToLower() --- doc/polycli_wrap-contract.md | 2 +- util/util.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/polycli_wrap-contract.md b/doc/polycli_wrap-contract.md index d7ae6be3..e67bae1e 100644 --- a/doc/polycli_wrap-contract.md +++ b/doc/polycli_wrap-contract.md @@ -19,7 +19,7 @@ polycli wrap-contract bytecode [flags] ## Usage -This command takes the bytecode that we want to be deployed for a new contract, and wraps its into the bytecode that we can use to create the contract. +This command takes the runtime bytecode, the bytecode deployed on-chain, as input and converts it into creation bytecode, the bytecode used to create the contract ```bash $ polycli wrap-contract 69602a60005260206000f3600052600a6016f3 diff --git a/util/util.go b/util/util.go index 9927871f..0c0fa159 100644 --- a/util/util.go +++ b/util/util.go @@ -319,8 +319,8 @@ func BlockUntilSuccessful(ctx context.Context, c *ethclient.Client, retryable fu } func WrapDeployedCode(deployedBytecode string, storageBytecode string) string { - deployedBytecode = strings.TrimPrefix(deployedBytecode, "0x") - storageBytecode = strings.TrimPrefix(storageBytecode, "0x") + deployedBytecode = strings.ToLower(strings.TrimPrefix(deployedBytecode, "0x")) + storageBytecode = strings.ToLower(strings.TrimPrefix(storageBytecode, "0x")) codeCopySize := len(deployedBytecode) / 2 codeCopyOffset := (len(storageBytecode)/2) + 13 + 8 // 13 for CODECOPY + 8 for RETURN