Skip to content

Commit

Permalink
Merge pull request #449 from 0xPolygon/cmd/wrapcontract
Browse files Browse the repository at this point in the history
Add cmd to wrap deployed bytecode
  • Loading branch information
xavier-romero authored Dec 10, 2024
2 parents 5d26f07 + bf6c5f5 commit 66dc357
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 16 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

</generated>

## Testing
Expand Down
18 changes: 2 additions & 16 deletions cmd/retest/retest.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 2 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -128,6 +129,7 @@ func NewPolycliCommand() *cobra.Command {
ulxly.ULxLyCmd,
version.VersionCmd,
wallet.WalletCmd,
wrapcontract.WrapContractCmd,
)
return cmd
}
18 changes: 18 additions & 0 deletions cmd/wrapcontract/usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
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

```

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
33 changes: 33 additions & 0 deletions cmd/wrapcontract/wrapcontract.go
Original file line number Diff line number Diff line change
@@ -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
},
}
2 changes: 2 additions & 0 deletions doc/polycli.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

64 changes: 64 additions & 0 deletions doc/polycli_wrap-contract.md
Original file line number Diff line number Diff line change
@@ -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 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

```

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.
20 changes: 20 additions & 0 deletions util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.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

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)
}

0 comments on commit 66dc357

Please sign in to comment.