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
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
anddeployedBytecode
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 originalgenesis.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
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]]"