Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate boilerplate or no code deploy common contracts #77 #78

Merged
merged 10 commits into from
Mar 13, 2019
6 changes: 3 additions & 3 deletions abi_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"os"
"strings"

abis "github.com/gochain-io/web3/abi"
"github.com/gochain-io/web3/assets"

"github.com/gochain-io/gochain/v3/accounts/abi"
)
Expand Down Expand Up @@ -34,5 +34,5 @@ func readAbi(reader io.Reader) (*abi.ABI, error) {
}

var bundledContracts = map[string]string{
"erc20": abis.ERC20,
"erc721": abis.ERC721}
"erc20": assets.ERC20ABI,
"erc721": assets.ERC721ABI}
File renamed without changes.
41 changes: 39 additions & 2 deletions abi/erc20.go → assets/erc20.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,43 @@
package abis
package assets

const ERC20 = `[
import (
"math/big"
)

type Erc20Params struct {
Symbol string
TokenName string
Cap *big.Int
Decimals int
Pausable bool
Mintable bool
Burnable bool
}

const ERC20Template = `pragma solidity ^0.5.2;

{{if .Pausable}} import "./lib/oz/contracts/token/ERC20/ERC20Pausable.sol"; {{end}}
{{if .Cap}} import "./lib/oz/contracts/token/ERC20/ERC20Capped.sol"; {{end}}
{{if .Burnable}} import "./lib/oz/contracts/token/ERC20/ERC20Burnable.sol"; {{end}}
{{if .Mintable}} import "./lib/oz/contracts/token/ERC20/ERC20Mintable.sol"; {{end}}
import "./lib/oz/contracts/token/ERC20/ERC20Detailed.sol";

contract {{.Symbol}}Token is
{{if .Cap}} ERC20Capped, {{end}}
{{if .Pausable}} ERC20Pausable, {{end}}
{{if .Burnable}} ERC20Burnable, {{end}}
{{if (and (.Mintable) (not .Cap))}} ERC20Mintable, {{end}}
ERC20Detailed {

// ------------------------------------------------------------------------
// Constructor
// ------------------------------------------------------------------------
constructor()
ERC20Detailed("{{.TokenName}}", "{{.Symbol}}", {{.Decimals}})
{{if .Cap}} ERC20Capped({{.Cap}}){{end}}
public {}
}`
const ERC20ABI = `[
{
"constant": true,
"inputs": [],
Expand Down
File renamed without changes.
35 changes: 33 additions & 2 deletions abi/erc721.go → assets/erc721.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,37 @@
package abis
package assets

const ERC721 = `[
type Erc721Params struct {
Symbol string
TokenName string
Pausable bool
MetadataMintable bool
Mintable bool
Burnable bool
}

const ERC721Template = `pragma solidity ^0.5.2;

{{if .Pausable}} import "./lib/oz/contracts/token/ERC721/ERC721Pausable.sol"; {{end}}
{{if .MetadataMintable}} import "./lib/oz/contracts/token/ERC721/ERC721MetadataMintable.sol"; {{end}}
{{if .Mintable}} import "./lib/oz/contracts/token/ERC721/ERC721Mintable.sol"; {{end}}
{{if .Burnable}} import "./lib/oz/contracts/token/ERC721/ERC721Burnable.sol"; {{end}}
import "./lib/oz/contracts/token/ERC721/ERC721Full.sol";

contract {{.Symbol}}Token is
{{if .Pausable}} ERC721Pausable, {{end}}
{{if .MetadataMintable}} ERC721MetadataMintable, {{end}}
{{if .Mintable}} ERC721Mintable, {{end}}
{{if .Burnable}} ERC721Burnable, {{end}}
ERC721Full {

// ------------------------------------------------------------------------
// Constructor
// ------------------------------------------------------------------------
constructor()
ERC721Full("{{.TokenName}}", "{{.Symbol}}")
public {}
}`
const ERC721ABI = `[
{
"constant": true,
"inputs": [],
Expand Down
170 changes: 170 additions & 0 deletions cmd/web3/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import (
"context"
"encoding/json"
"fmt"
"html/template"
"io/ioutil"
"log"
"math/big"
"os"
"os/exec"
"os/signal"
"sort"
"strings"
Expand All @@ -20,6 +22,7 @@ import (
"github.com/gochain-io/gochain/v3/common/hexutil"
"github.com/gochain-io/gochain/v3/core/types"
"github.com/gochain-io/web3"
"github.com/gochain-io/web3/assets"
"github.com/urfave/cli"
)

Expand Down Expand Up @@ -360,6 +363,91 @@ func main() {
}
},
},
{
Name: "generate",
Usage: "Generate an ABI code",
Aliases: []string{"g"},
Subcommands: []cli.Command{
{
Name: "contract",
Usage: "Generate a contract",
Aliases: []string{"c"},
Subcommands: []cli.Command{
{
Name: "erc20",
Usage: "Generate a erc20 contract",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "pausable, p",
Usage: "Pausable contract.",
},
cli.BoolFlag{
Name: "mintable, m",
Usage: "Mintable contract.",
},
cli.BoolFlag{
Name: "burnable, b",
Usage: "Burnable contract.",
},
cli.StringFlag{
Name: "symbol, s",
Usage: "Token Symbol.",
},
cli.StringFlag{
Name: "name, n",
Usage: "Token Name",
},
cli.StringFlag{
Name: "capped, c",
Usage: "Cap, total supply(in GO/ETH)",
},
cli.IntFlag{
Name: "decimals, d",
Usage: "Decimals",
Value: 18,
},
},
Action: func(c *cli.Context) {
GenerateContract(ctx, "erc20", c)
},
},
{
Name: "erc721",
Usage: "Generate a erc721 contract",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "pausable, p",
Usage: "Pausable contract.",
},
cli.BoolFlag{
Name: "mintable, m",
Usage: "Mintable contract.",
},
cli.BoolFlag{
Name: "burnable, b",
Usage: "Burnable contract.",
},
cli.BoolFlag{
Name: "metadata-mintable, mm",
Usage: "Contract with a mintable metadata.",
},
cli.StringFlag{
Name: "symbol, s",
Usage: "Token Symbol.",
},
cli.StringFlag{
Name: "name, n",
Usage: "Token Name",
},
},
Action: func(c *cli.Context) {
GenerateContract(ctx, "erc721", c)
},
},
},
},
},
},
}
app.Run(os.Args)
}
Expand Down Expand Up @@ -871,6 +959,88 @@ func Send(ctx context.Context, rpcURL, privateKey, toAddress, amount string) {
fmt.Println("Transaction address:", tx.Hash.Hex())
}

func GenerateContract(ctx context.Context, contractType string, c *cli.Context) {
if _, err := os.Stat("lib/oz"); os.IsNotExist(err) {
cmd := exec.Command("git", "clone", "--depth", "1", "--branch", "master", "https://github.com/OpenZeppelin/openzeppelin-solidity", "lib/oz")
log.Printf("Cloning OpenZeppeling repo...")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
log.Fatalf("Cloning finished with error: %v", err)
}
}
if contractType == "erc20" {
var capped *big.Int
decimals := c.Int("decimals")
if decimals <= 0 {
log.Fatalln("Decimals should be greater than 0")
}
if c.String("capped") != "" {
var ok bool
capped, ok = new(big.Int).SetString(c.String("capped"), 10)
if !ok {
log.Fatalln("Cannot parse capped value")
}
if capped.Cmp(big.NewInt(0)) < 1 {
log.Fatalln("Capped should be greater than 0")
}
capped.Mul(capped, new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(decimals)), nil))
}
if c.String("symbol") == "" {
log.Fatalln("Symbol is required")
}
if c.String("name") == "" {
log.Fatalln("Name is required")
}

params := assets.Erc20Params{
Symbol: c.String("symbol"),
TokenName: c.String("name"),
Cap: capped,
Pausable: c.Bool("pausable"),
Mintable: c.Bool("mintable"),
Burnable: c.Bool("burnable"),
Decimals: decimals,
}
processTemplate(params, params.TokenName, assets.ERC20Template)
} else if contractType == "erc721" {
if c.String("symbol") == "" {
log.Fatalln("Symbol is required")
}
if c.String("name") == "" {
log.Fatalln("Name is required")
}

params := assets.Erc721Params{
Symbol: c.String("symbol"),
TokenName: c.String("name"),
Pausable: c.Bool("pausable"),
Mintable: c.Bool("mintable"),
Burnable: c.Bool("burnable"),
MetadataMintable: c.Bool("metadata-mintable"),
}
processTemplate(params, params.TokenName, assets.ERC721Template)
}
}

func processTemplate(params interface{}, fileName, contractTemplate string) {
tmpl, err := template.New("contract").Parse(contractTemplate)
if err != nil {
log.Fatalf("Cannot parse the template: %v", err)
}
f, err := os.Create(fileName + ".sol")
if err != nil {
log.Fatalf("Cannot create the file: %v", err)
return
}
err = tmpl.Execute(f, params)
if err != nil {
log.Fatalf("Cannot execute the template: %v", err)
return
}
fmt.Println("The sample contract has been successfully written to", fileName+".sol", "file")
}
func printReceiptDetails(r *web3.Receipt, myabi *abi.ABI) {
var logs []web3.Event
var err error
Expand Down