Skip to main content

Smart Contract Predeployment

Overview

This guide goes into detail on how to predeploy a Smart Contract on fresh Polygon Edge networks.

What is predeployment?

Predeployment is a similar process to deployment - users want to have their Smart Contract present on the chain. Instead of manually deploying a Smart Contract on a running chain through transactions, some users want their Smart Contracts to be present and queryable from block 1, at a certain address they specify.

This is where predeployment comes in. Polygon Edge allows users to specify Solidity Smart Contracts they want to see present in the blockchain from block 1, and not have to worry about orchestrating deployments as soon as the chain is running.

Video presentation

smart contract predeployment- video

How do I predeploy a Smart Contract?

Let's say that you have the following Smart Contract in Solidity:

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

contract Greeter {
struct MyStruct {
string name;
}

MyStruct private greeting;

int256 num;
string secondStr;

constructor(
MyStruct[] memory myStr,
int256[] memory myArgNum,
string memory mySecondStr
) {
greeting = myStr[1];
num = myArgNum[0];
secondStr = mySecondStr;
}

function greet() public view returns (string memory) {
return greeting.name;
}

function greetNum() public view returns (int256) {
return num;
}

function greetSecond() public view returns (string memory) {
return secondStr;
}
}

A few things to note:

  • The first constructor argument is a structure, that has a string field
  • The second constructor argument is an array of numbers
  • The third constructor argument is a string

To predeploy contracts in Polygon Edge, you're going to need the following:

  • The artifact ABI that contains the abi, bytecode and deployedBytecode fields as part of a JSON file
  • The values you want to pass in as arguments to the constructor, if any

An example of an artifact ABI generated by Hardhat (located in /artifacts/contracts/<ContractName.sol>/<ContractName>.json):

{
...
"abi": [
{
"inputs": [
{
"components": [
{
"internalType": "string",
"name": "name",
"type": "string"
}
],
"internalType": "struct Greeter.MyStruct[]",
"name": "myStr",
"type": "tuple[]"
},
{
"internalType": "int256[]",
"name": "myArgNum",
"type": "int256[]"
},
{
"internalType": "string",
"name": "mySecondStr",
"type": "string"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "greet",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "greetNum",
"outputs": [
{
"internalType": "int256",
"name": "",
"type": "int256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "greetSecond",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
}
],
"bytecode": "0x60806040523480156200001157600080fd5b5060405162000a4738038062000a478339818101604052810190620000379190620003e4565b826001815181106200004e576200004d62000635565b5b602002602001015160008082015181600001908051906020019062000075929190620000c0565b509050508160008151811062000090576200008f62000635565b5b60200260200101516001819055508060029080519060200190620000b6929190620000c0565b50505050620006e1565b828054620000ce906200059a565b90600052602060002090601f016020900481019282620000f257600085556200013e565b82601f106200010d57805160ff19168380011785556200013e565b828001600101855582156200013e579182015b828111156200013d57825182559160200191906001019062000120565b5b5090506200014d919062000151565b5090565b5b808211156200016c57600081600090555060010162000152565b5090565b6000620001876200018184620004c6565b6200049d565b90508083825260208201905082856020860282011115620001ad57620001ac620006a2565b5b60005b85811015620001e15781620001c6888262000338565b845260208401935060208301925050600181019050620001b0565b5050509392505050565b600062000202620001fc84620004f5565b6200049d565b90508083825260208201905082856020860282011115620002285762000227620006a2565b5b60005b858110156200027d57815167ffffffffffffffff81111562000252576200025162000693565b5b80860162000261898262000382565b855260208501945060208401935050506001810190506200022b565b5050509392505050565b60006200029e620002988462000524565b6200049d565b905082815260208101848484011115620002bd57620002bc620006a7565b5b620002ca84828562000564565b509392505050565b600082601f830112620002ea57620002e962000693565b5b8151620002fc84826020860162000170565b91505092915050565b600082601f8301126200031d576200031c62000693565b5b81516200032f848260208601620001eb565b91505092915050565b6000815190506200034981620006c7565b92915050565b600082601f83011262000367576200036662000693565b5b81516200037984826020860162000287565b91505092915050565b6000602082840312156200039b576200039a62000698565b5b620003a760206200049d565b9050600082015167ffffffffffffffff811115620003ca57620003c96200069d565b5b620003d8848285016200034f565b60008301525092915050565b6000806000606084860312156200040057620003ff620006b1565b5b600084015167ffffffffffffffff811115620004215762000420620006ac565b5b6200042f8682870162000305565b935050602084015167ffffffffffffffff811115620004535762000452620006ac565b5b6200046186828701620002d2565b925050604084015167ffffffffffffffff811115620004855762000484620006ac565b5b62000493868287016200034f565b9150509250925092565b6000620004a9620004bc565b9050620004b78282620005d0565b919050565b6000604051905090565b600067ffffffffffffffff821115620004e457620004e362000664565b5b602082029050602081019050919050565b600067ffffffffffffffff82111562000513576200051262000664565b5b602082029050602081019050919050565b600067ffffffffffffffff82111562000542576200054162000664565b5b6200054d82620006b6565b9050602081019050919050565b6000819050919050565b60005b838110156200058457808201518184015260208101905062000567565b8381111562000594576000848401525b50505050565b60006002820490506001821680620005b357607f821691505b60208210811415620005ca57620005c962000606565b5b50919050565b620005db82620006b6565b810181811067ffffffffffffffff82111715620005fd57620005fc62000664565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b620006d2816200055a565b8114620006de57600080fd5b50565b61035680620006f16000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806388c43be314610046578063935e341114610064578063cfae321714610082575b600080fd5b61004e6100a0565b60405161005b9190610233565b60405180910390f35b61006c610132565b6040516100799190610218565b60405180910390f35b61008a61013c565b6040516100979190610233565b60405180910390f35b6060600280546100af906102ae565b80601f01602080910402602001604051908101604052809291908181526020018280546100db906102ae565b80156101285780601f106100fd57610100808354040283529160200191610128565b820191906000526020600020905b81548152906001019060200180831161010b57829003601f168201915b5050505050905090565b6000600154905090565b606060008001805461014d906102ae565b80601f0160208091040260200160405190810160405280929190818152602001828054610179906102ae565b80156101c65780601f1061019b576101008083540402835291602001916101c6565b820191906000526020600020905b8154815290600101906020018083116101a957829003601f168201915b5050505050905090565b6101d981610271565b82525050565b60006101ea82610255565b6101f48185610260565b935061020481856020860161027b565b61020d8161030f565b840191505092915050565b600060208201905061022d60008301846101d0565b92915050565b6000602082019050818103600083015261024d81846101df565b905092915050565b600081519050919050565b600082825260208201905092915050565b6000819050919050565b60005b8381101561029957808201518184015260208101905061027e565b838111156102a8576000848401525b50505050565b600060028204905060018216806102c657607f821691505b602082108114156102da576102d96102e0565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000601f19601f830116905091905056fea26469706673582212206df69f8411f826ef8a02047a7a81d22fea88b2bc7d54e9ecbeaf6e5c1fa7c21d64736f6c63430008070033",
"deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c806388c43be314610046578063935e341114610064578063cfae321714610082575b600080fd5b61004e6100a0565b60405161005b9190610233565b60405180910390f35b61006c610132565b6040516100799190610218565b60405180910390f35b61008a61013c565b6040516100979190610233565b60405180910390f35b6060600280546100af906102ae565b80601f01602080910402602001604051908101604052809291908181526020018280546100db906102ae565b80156101285780601f106100fd57610100808354040283529160200191610128565b820191906000526020600020905b81548152906001019060200180831161010b57829003601f168201915b5050505050905090565b6000600154905090565b606060008001805461014d906102ae565b80601f0160208091040260200160405190810160405280929190818152602001828054610179906102ae565b80156101c65780601f1061019b576101008083540402835291602001916101c6565b820191906000526020600020905b8154815290600101906020018083116101a957829003601f168201915b5050505050905090565b6101d981610271565b82525050565b60006101ea82610255565b6101f48185610260565b935061020481856020860161027b565b61020d8161030f565b840191505092915050565b600060208201905061022d60008301846101d0565b92915050565b6000602082019050818103600083015261024d81846101df565b905092915050565b600081519050919050565b600082825260208201905092915050565b6000819050919050565b60005b8381101561029957808201518184015260208101905061027e565b838111156102a8576000848401525b50505050565b600060028204905060018216806102c657607f821691505b602082108114156102da576102d96102e0565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000601f19601f830116905091905056fea26469706673582212206df69f8411f826ef8a02047a7a81d22fea88b2bc7d54e9ecbeaf6e5c1fa7c21d64736f6c63430008070033",
...
}

To predeploy the specified Greeter Smart Contract, you can run the genesis predeploy command: polygon-edge genesis predeploy --chain ./genesis.json --artifacts-path ./Greeter.json --predeploy-address "0x01110" --constructor-args "[[a],[b]]" --constructor-args "[123, 456]" --constructor-args "myArg"

A few things to note here:

  • --artifacts-path specifies the path to the artifacts file that contains the deployedBytecode and ABI (this is just standard Hardhat output json for the artifact)
  • --chain specifies the path to the original genesis.json
  • --predeploy-address specifies the desired predeploy address (you can’t predeploy to a taken address, or to reserved addresses (for example the Staking SC address)
  • --constructor-args specify the constructor args, whatever they may be. For detailed information on how to specify the constructor arguments, take a look at a detailed guide below
Be careful when specifying a predeploy address

Predeploy addresses need to meet certain criteria:

  • they need to be equal or above the address 0x01100
  • they cannot be reused (meaning there cannot be 2 predeployments to the same address)
  • they cannot use reserved addresses (for example the Staking SC address)

How do I specify constructor arguments?

There are several ways for specifying the constructor arguments, depending on the type of constructor argument.

Structures as arguments

Specifying structures as arguments is pretty straightforward.

Example structure:

  struct MyStruct {
string name;
int256 number;
}

// ...

constructor(MyStruct myStr) {
// ...
}

Structures are specified as an array of values (with the array elements being the fields in declaration order), surrounded by square brackets ([]): polygon-edge genesis predeploy ... --constructor-args "["some string value",123]"

Arrays as arguments

Example constructor:

  constructor(int256[] memory myArr) {
// ...
}

Arrays are represented as values surrounded by square brackets ([]): polygon-edge genesis predeploy ... --constructor-args "[123,456,789]"

Single-types as arguments

Example constructor:

  constructor(int256 myNum) {
// ...
}

Single-type values are represented as regular values without any brackets: polygon-edge genesis predeploy ... --constructor-args 123

Combination of all types as arguments

Combinations of different argument types (for example, arrays of structures) are specified by the rules mentioned above.

Example structure:

  struct MyStruct {
string name;
int256 number;
}

// ...

constructor(MyStruct[] memory myStrs) {
// ...
}

To specify an array of structures like this, the 3 basic rules stated above need to be combined: polygon-edge genesis predeploy ... --constructor-args "[["value 1", 123],["value 2", 456],["value 3", 789]]"