create-stylus 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +6 -0
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/src/extensions.json +6 -0
- package/templates/base/package.json +1 -1
- package/templates/base/packages/nextjs/utils/scaffold-stylus/supportedChains.ts +37 -2
- package/templates/base/packages/stylus/.env.example +20 -0
- package/templates/base/packages/stylus/counter/.cargo/config.toml +18 -0
- package/templates/base/packages/stylus/counter/Cargo.lock +5788 -0
- package/templates/base/packages/stylus/counter/Cargo.toml +46 -0
- package/templates/base/packages/stylus/counter/rust-toolchain.toml +2 -0
- package/templates/base/packages/stylus/counter/src/lib.rs +121 -0
- package/templates/base/packages/stylus/counter/src/main.rs +10 -0
- package/templates/base/packages/stylus/scripts/deploy.ts +9 -1
- package/templates/base/packages/stylus/scripts/deploy_contract.ts +48 -0
- package/templates/base/packages/stylus/scripts/utils/command.ts +2 -1
- package/templates/base/packages/stylus/scripts/utils/contract.ts +2 -4
- package/templates/base/packages/stylus/scripts/utils/network.ts +75 -1
- package/templates/base/packages/stylus/scripts/utils/type.ts +1 -0
- package/templates/base/readme.md +9 -1
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "stylus-hello-world"
|
|
3
|
+
version = "0.1.11"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
license = "MIT OR Apache-2.0"
|
|
6
|
+
homepage = "https://github.com/OffchainLabs/stylus-hello-world"
|
|
7
|
+
repository = "https://github.com/OffchainLabs/stylus-hello-world"
|
|
8
|
+
keywords = ["arbitrum", "ethereum", "stylus", "alloy"]
|
|
9
|
+
description = "Stylus hello world example"
|
|
10
|
+
|
|
11
|
+
[dependencies]
|
|
12
|
+
alloy-primitives = "=0.8.20"
|
|
13
|
+
alloy-sol-types = "=0.8.20"
|
|
14
|
+
stylus-sdk = "0.9.0"
|
|
15
|
+
hex = { version = "0.4", default-features = false }
|
|
16
|
+
|
|
17
|
+
[dev-dependencies]
|
|
18
|
+
alloy-primitives = { version = "=0.8.20", features = ["sha3-keccak"] }
|
|
19
|
+
tokio = { version = "1.12.0", features = ["full"] }
|
|
20
|
+
ethers = "2.0"
|
|
21
|
+
eyre = "0.6.8"
|
|
22
|
+
stylus-sdk = { version = "0.9.0", features = ["stylus-test"] }
|
|
23
|
+
dotenv = "0.15.0"
|
|
24
|
+
|
|
25
|
+
[features]
|
|
26
|
+
default = ["mini-alloc"]
|
|
27
|
+
export-abi = ["stylus-sdk/export-abi"]
|
|
28
|
+
debug = ["stylus-sdk/debug"]
|
|
29
|
+
mini-alloc = ["stylus-sdk/mini-alloc"]
|
|
30
|
+
|
|
31
|
+
[[bin]]
|
|
32
|
+
name = "stylus-hello-world"
|
|
33
|
+
path = "src/main.rs"
|
|
34
|
+
|
|
35
|
+
[lib]
|
|
36
|
+
crate-type = ["lib", "cdylib"]
|
|
37
|
+
|
|
38
|
+
[profile.release]
|
|
39
|
+
codegen-units = 1
|
|
40
|
+
strip = true
|
|
41
|
+
lto = true
|
|
42
|
+
panic = "abort"
|
|
43
|
+
|
|
44
|
+
# If you need to reduce the binary size, it is advisable to try other
|
|
45
|
+
# optimization levels, such as "s" and "z"
|
|
46
|
+
opt-level = 3
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
//!
|
|
2
|
+
//! Stylus Hello World
|
|
3
|
+
//!
|
|
4
|
+
//! The following contract implements the Counter example from Foundry.
|
|
5
|
+
//!
|
|
6
|
+
//! ```solidity
|
|
7
|
+
//! contract Counter {
|
|
8
|
+
//! uint256 public number;
|
|
9
|
+
//! function setNumber(uint256 newNumber) public {
|
|
10
|
+
//! number = newNumber;
|
|
11
|
+
//! }
|
|
12
|
+
//! function increment() public {
|
|
13
|
+
//! number++;
|
|
14
|
+
//! }
|
|
15
|
+
//! }
|
|
16
|
+
//! ```
|
|
17
|
+
//!
|
|
18
|
+
//! The program is ABI-equivalent with Solidity, which means you can call it from both Solidity and Rust.
|
|
19
|
+
//! To do this, run `cargo stylus export-abi`.
|
|
20
|
+
//!
|
|
21
|
+
//! Note: this code is a template-only and has not been audited.
|
|
22
|
+
//!
|
|
23
|
+
// Allow `cargo stylus export-abi` to generate a main function.
|
|
24
|
+
#![cfg_attr(not(any(test, feature = "export-abi")), no_main)]
|
|
25
|
+
#![cfg_attr(not(any(test, feature = "export-abi")), no_std)]
|
|
26
|
+
|
|
27
|
+
#[macro_use]
|
|
28
|
+
extern crate alloc;
|
|
29
|
+
|
|
30
|
+
use alloc::vec::Vec;
|
|
31
|
+
|
|
32
|
+
/// Import items from the SDK. The prelude contains common traits and macros.
|
|
33
|
+
use stylus_sdk::{alloy_primitives::U256, prelude::*};
|
|
34
|
+
|
|
35
|
+
// Define some persistent storage using the Solidity ABI.
|
|
36
|
+
// `Counter` will be the entrypoint.
|
|
37
|
+
sol_storage! {
|
|
38
|
+
#[entrypoint]
|
|
39
|
+
pub struct Counter {
|
|
40
|
+
uint256 number;
|
|
41
|
+
bool is_initialized;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/// Declare that `Counter` is a contract with the following external methods.
|
|
46
|
+
#[public]
|
|
47
|
+
impl Counter {
|
|
48
|
+
pub fn initialize(&mut self, initial_number: U256) {
|
|
49
|
+
if !self.is_initialized.get() {
|
|
50
|
+
self.number.set(initial_number);
|
|
51
|
+
self.is_initialized.set(true);
|
|
52
|
+
} else {
|
|
53
|
+
panic!("Counter already initialized");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/// Gets the number from storage.
|
|
58
|
+
pub fn number(&self) -> U256 {
|
|
59
|
+
self.number.get()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/// Sets a number in storage to a user-specified value.
|
|
63
|
+
pub fn set_number(&mut self, new_number: U256) {
|
|
64
|
+
self.number.set(new_number);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/// Sets a number in storage to a user-specified value.
|
|
68
|
+
pub fn mul_number(&mut self, new_number: U256) {
|
|
69
|
+
self.number.set(new_number * self.number.get());
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/// Sets a number in storage to a user-specified value.
|
|
73
|
+
pub fn add_number(&mut self, new_number: U256) {
|
|
74
|
+
self.number.set(new_number + self.number.get());
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/// Increments `number` and updates its value in storage.
|
|
78
|
+
pub fn increment(&mut self) {
|
|
79
|
+
let number = self.number.get();
|
|
80
|
+
self.set_number(number + U256::from(1));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/// Adds the wei value from msg_value to the number in storage.
|
|
84
|
+
#[payable]
|
|
85
|
+
pub fn add_from_msg_value(&mut self) {
|
|
86
|
+
let number = self.number.get();
|
|
87
|
+
self.set_number(number + self.vm().msg_value());
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
#[cfg(test)]
|
|
92
|
+
mod test {
|
|
93
|
+
use super::*;
|
|
94
|
+
|
|
95
|
+
#[test]
|
|
96
|
+
fn test_counter() {
|
|
97
|
+
use stylus_sdk::testing::*;
|
|
98
|
+
let vm = TestVM::default();
|
|
99
|
+
let mut contract = Counter::from(&vm);
|
|
100
|
+
|
|
101
|
+
assert_eq!(U256::ZERO, contract.number());
|
|
102
|
+
|
|
103
|
+
contract.increment();
|
|
104
|
+
assert_eq!(U256::from(1), contract.number());
|
|
105
|
+
|
|
106
|
+
contract.add_number(U256::from(3));
|
|
107
|
+
assert_eq!(U256::from(4), contract.number());
|
|
108
|
+
|
|
109
|
+
contract.mul_number(U256::from(2));
|
|
110
|
+
assert_eq!(U256::from(8), contract.number());
|
|
111
|
+
|
|
112
|
+
contract.set_number(U256::from(100));
|
|
113
|
+
assert_eq!(U256::from(100), contract.number());
|
|
114
|
+
|
|
115
|
+
// Override the msg value for future contract method invocations.
|
|
116
|
+
vm.set_value(U256::from(2));
|
|
117
|
+
|
|
118
|
+
contract.add_from_msg_value();
|
|
119
|
+
assert_eq!(U256::from(102), contract.number());
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -32,7 +32,15 @@ export default async function deployScript(deployOptions: DeployOptions) {
|
|
|
32
32
|
...deployOptions,
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
// EXAMPLE: Deploy to Orbit Chains, uncomment to try
|
|
36
|
+
// await deployStylusContract({
|
|
37
|
+
// contract: "counter",
|
|
38
|
+
// constructorArgs: [100],
|
|
39
|
+
// isOrbit: true,
|
|
40
|
+
// ...deployOptions,
|
|
41
|
+
// });
|
|
42
|
+
|
|
43
|
+
// EXAMPLE: Deploy your contract with a custom name, uncomment to try
|
|
36
44
|
// await deployStylusContract({
|
|
37
45
|
// contract: "your-contract",
|
|
38
46
|
// constructorArgs: [config.deployerAddress],
|
|
@@ -4,11 +4,17 @@ import {
|
|
|
4
4
|
executeCommand,
|
|
5
5
|
extractDeploymentInfo,
|
|
6
6
|
saveDeployment,
|
|
7
|
+
ORBIT_CHAINS,
|
|
7
8
|
// estimateGasPrice,
|
|
8
9
|
} from "./utils/";
|
|
9
10
|
import { exportStylusAbi } from "./export_abi";
|
|
10
11
|
import { DeployOptions } from "./utils/type";
|
|
11
12
|
import { buildDeployCommand } from "./utils/command";
|
|
13
|
+
import { Chain, createPublicClient, createWalletClient, http } from "viem";
|
|
14
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
15
|
+
|
|
16
|
+
import { arbitrumNitro } from "../../nextjs/utils/scaffold-stylus/supportedChains";
|
|
17
|
+
import deployedContracts from "../../nextjs/contracts/deployedContracts";
|
|
12
18
|
|
|
13
19
|
/**
|
|
14
20
|
* Deploy a single contract using cargo stylus
|
|
@@ -61,6 +67,48 @@ export default async function deployStylusContract(
|
|
|
61
67
|
config.chain?.id,
|
|
62
68
|
);
|
|
63
69
|
|
|
70
|
+
// Call the initialize function if orbit deployment
|
|
71
|
+
if (
|
|
72
|
+
!!deployOptions.isOrbit &&
|
|
73
|
+
config.chain?.id !== arbitrumNitro?.id.toString()
|
|
74
|
+
) {
|
|
75
|
+
const orbitChain = ORBIT_CHAINS.find(
|
|
76
|
+
(chain) => chain.id.toString() === config.chain?.id,
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
if (!orbitChain) {
|
|
80
|
+
throw new Error(
|
|
81
|
+
`Chain ${config.chain?.id} is not supported for orbit deployment`,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const publicClient = createPublicClient({
|
|
86
|
+
chain: orbitChain as unknown as Chain,
|
|
87
|
+
transport: http(),
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// need wallet client to sign the transaction
|
|
91
|
+
const walletClient = createWalletClient({
|
|
92
|
+
chain: orbitChain as unknown as Chain,
|
|
93
|
+
transport: http(),
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const account = privateKeyToAccount(config.privateKey as `0x${string}`);
|
|
97
|
+
|
|
98
|
+
const { request } = await publicClient.simulateContract({
|
|
99
|
+
account,
|
|
100
|
+
address: deploymentInfo.address,
|
|
101
|
+
// @ts-expect-error deployed contract is empty at the beginning
|
|
102
|
+
abi: deployedContracts[config.chain.id][config.contractName].abi,
|
|
103
|
+
functionName: "initialize",
|
|
104
|
+
args: deployOptions.constructorArgs,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const initTxHash = await walletClient.writeContract(request);
|
|
108
|
+
|
|
109
|
+
console.log("Initialize transaction hash: ", initTxHash);
|
|
110
|
+
}
|
|
111
|
+
|
|
64
112
|
// Step 3: Verify the contract
|
|
65
113
|
if (deployOptions.verify) {
|
|
66
114
|
try {
|
|
@@ -22,7 +22,8 @@ export async function buildDeployCommand(
|
|
|
22
22
|
|
|
23
23
|
if (
|
|
24
24
|
deployOptions.constructorArgs &&
|
|
25
|
-
deployOptions.constructorArgs.length > 0
|
|
25
|
+
deployOptions.constructorArgs.length > 0 &&
|
|
26
|
+
!deployOptions.isOrbit
|
|
26
27
|
) {
|
|
27
28
|
baseCommand += ` --constructor-args ${deployOptions.constructorArgs.map((arg) => `"${arg}"`).join(" ")} `;
|
|
28
29
|
}
|
|
@@ -154,9 +154,7 @@ export async function generateTsAbi(
|
|
|
154
154
|
};
|
|
155
155
|
|
|
156
156
|
let deployedContractsObj: any = {};
|
|
157
|
-
const fileHeader =
|
|
158
|
-
generatedContractComment +
|
|
159
|
-
'import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract";\n\n';
|
|
157
|
+
const fileHeader = generatedContractComment + "\n\n";
|
|
160
158
|
|
|
161
159
|
if (fs.existsSync(TARGET_FILE)) {
|
|
162
160
|
const fileContent = fs.readFileSync(TARGET_FILE, "utf8");
|
|
@@ -177,7 +175,7 @@ export async function generateTsAbi(
|
|
|
177
175
|
|
|
178
176
|
const contractsString = JSON.stringify(deployedContractsObj, null, 2);
|
|
179
177
|
|
|
180
|
-
const output = `${fileHeader}const deployedContracts = ${contractsString} as const;\n\nexport default deployedContracts
|
|
178
|
+
const output = `${fileHeader}const deployedContracts = ${contractsString} as const;\n\nexport default deployedContracts;\n`;
|
|
181
179
|
|
|
182
180
|
if (!fs.existsSync(TARGET_DIR)) {
|
|
183
181
|
fs.mkdirSync(TARGET_DIR);
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { arbitrum, arbitrumNova, arbitrumSepolia } from "viem/chains";
|
|
2
2
|
import { Address, Chain } from "viem";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
arbitrumNitro,
|
|
5
|
+
superposition,
|
|
6
|
+
eduChainTestnet,
|
|
7
|
+
superpositionTestnet,
|
|
8
|
+
eduChain,
|
|
9
|
+
} from "../../../nextjs/utils/scaffold-stylus/supportedChains";
|
|
4
10
|
import * as path from "path";
|
|
5
11
|
import * as fs from "fs";
|
|
6
12
|
import { config as dotenvConfig } from "dotenv";
|
|
@@ -16,6 +22,10 @@ export const SUPPORTED_NETWORKS: Record<string, Chain> = {
|
|
|
16
22
|
arbitrumSepolia,
|
|
17
23
|
arbitrumNitro: arbitrumNitro as Chain,
|
|
18
24
|
arbitrumNova: arbitrumNova as Chain,
|
|
25
|
+
eduChainTestnet: eduChainTestnet as unknown as Chain,
|
|
26
|
+
eduChain: eduChain as unknown as Chain,
|
|
27
|
+
superposition: superposition as Chain,
|
|
28
|
+
superpositionTestnet: superpositionTestnet as Chain,
|
|
19
29
|
};
|
|
20
30
|
|
|
21
31
|
export const ALIASES: Record<string, string> = {
|
|
@@ -23,8 +33,20 @@ export const ALIASES: Record<string, string> = {
|
|
|
23
33
|
sepolia: "arbitrumSepolia",
|
|
24
34
|
devnet: "arbitrumNitro",
|
|
25
35
|
nova: "arbitrumNova",
|
|
36
|
+
educhain_testnet: "educhainTestnet",
|
|
37
|
+
educhain: "eduChain",
|
|
38
|
+
superposition: "superposition",
|
|
39
|
+
superposition_testnet: "superpositionTestnet",
|
|
26
40
|
};
|
|
27
41
|
|
|
42
|
+
// TODO: add more compatible Orbit Chains here
|
|
43
|
+
export const ORBIT_CHAINS: Chain[] = [
|
|
44
|
+
eduChain as unknown as Chain,
|
|
45
|
+
eduChainTestnet as unknown as Chain,
|
|
46
|
+
superposition as Chain,
|
|
47
|
+
superpositionTestnet as Chain,
|
|
48
|
+
];
|
|
49
|
+
|
|
28
50
|
export function getChain(networkName: string): SupportedNetworkMinimal | null {
|
|
29
51
|
try {
|
|
30
52
|
const actualNetworkName = ALIASES[networkName.toLowerCase()] || networkName;
|
|
@@ -75,6 +97,30 @@ export function getPrivateKey(networkName: string): string {
|
|
|
75
97
|
} else {
|
|
76
98
|
throw new Error("PRIVATE_KEY_NOVA is not set");
|
|
77
99
|
}
|
|
100
|
+
case "educhaintestnet":
|
|
101
|
+
if (process.env["PRIVATE_KEY_EDUCHAIN_TESTNET"]) {
|
|
102
|
+
return process.env["PRIVATE_KEY_EDUCHAIN_TESTNET"];
|
|
103
|
+
} else {
|
|
104
|
+
throw new Error("PRIVATE_KEY_EDUCHAIN_TESTNET is not set");
|
|
105
|
+
}
|
|
106
|
+
case "educhain":
|
|
107
|
+
if (process.env["PRIVATE_KEY_EDUCHAIN"]) {
|
|
108
|
+
return process.env["PRIVATE_KEY_EDUCHAIN"];
|
|
109
|
+
} else {
|
|
110
|
+
throw new Error("PRIVATE_KEY_EDUCHAIN is not set");
|
|
111
|
+
}
|
|
112
|
+
case "superposition":
|
|
113
|
+
if (process.env["PRIVATE_KEY_SUPERPOSITION"]) {
|
|
114
|
+
return process.env["PRIVATE_KEY_SUPERPOSITION"];
|
|
115
|
+
} else {
|
|
116
|
+
throw new Error("PRIVATE_KEY_SUPERPOSITION is not set");
|
|
117
|
+
}
|
|
118
|
+
case "superpositiontestnet":
|
|
119
|
+
if (process.env["PRIVATE_KEY_SUPERPOSITION_TESTNET"]) {
|
|
120
|
+
return process.env["PRIVATE_KEY_SUPERPOSITION_TESTNET"];
|
|
121
|
+
} else {
|
|
122
|
+
throw new Error("PRIVATE_KEY_SUPERPOSITION_TESTNET is not set");
|
|
123
|
+
}
|
|
78
124
|
default:
|
|
79
125
|
return (
|
|
80
126
|
process.env["PRIVATE_KEY"] ||
|
|
@@ -92,6 +138,14 @@ export const getAccountAddress = (networkName: string): Address | undefined => {
|
|
|
92
138
|
return process.env["ACCOUNT_ADDRESS_SEPOLIA"] as Address;
|
|
93
139
|
case "arbitrumnova":
|
|
94
140
|
return process.env["ACCOUNT_ADDRESS_NOVA"] as Address;
|
|
141
|
+
case "educhaintestnet":
|
|
142
|
+
return process.env["ACCOUNT_ADDRESS_EDUCHAIN_TESTNET"] as Address;
|
|
143
|
+
case "educhain":
|
|
144
|
+
return process.env["ACCOUNT_ADDRESS_EDUCHAIN"] as Address;
|
|
145
|
+
case "superposition":
|
|
146
|
+
return process.env["ACCOUNT_ADDRESS_SUPERPOSITION"] as Address;
|
|
147
|
+
case "superpositiontestnet":
|
|
148
|
+
return process.env["ACCOUNT_ADDRESS_SUPERPOSITION_TESTNET"] as Address;
|
|
95
149
|
default:
|
|
96
150
|
return (
|
|
97
151
|
(process.env["ACCOUNT_ADDRESS"] as Address) ||
|
|
@@ -118,6 +172,26 @@ function getRpcUrlFromChain(chain: Chain): string {
|
|
|
118
172
|
return process.env["RPC_URL_NOVA"];
|
|
119
173
|
}
|
|
120
174
|
break;
|
|
175
|
+
case eduChainTestnet.id:
|
|
176
|
+
if (process.env["RPC_URL_EDUCHAIN_TESTNET"]) {
|
|
177
|
+
return process.env["RPC_URL_EDUCHAIN_TESTNET"];
|
|
178
|
+
}
|
|
179
|
+
break;
|
|
180
|
+
case eduChain.id:
|
|
181
|
+
if (process.env["RPC_URL_EDUCHAIN"]) {
|
|
182
|
+
return process.env["RPC_URL_EDUCHAIN"];
|
|
183
|
+
}
|
|
184
|
+
break;
|
|
185
|
+
case superposition.id:
|
|
186
|
+
if (process.env["RPC_URL_SUPERPOSITION"]) {
|
|
187
|
+
return process.env["RPC_URL_SUPERPOSITION"];
|
|
188
|
+
}
|
|
189
|
+
break;
|
|
190
|
+
case superpositionTestnet.id:
|
|
191
|
+
if (process.env["RPC_URL_SUPERPOSITION_TESTNET"]) {
|
|
192
|
+
return process.env["RPC_URL_SUPERPOSITION_TESTNET"];
|
|
193
|
+
}
|
|
194
|
+
break;
|
|
121
195
|
default:
|
|
122
196
|
if (process.env["RPC_URL"]) {
|
|
123
197
|
return process.env["RPC_URL"];
|
package/templates/base/readme.md
CHANGED
|
@@ -194,7 +194,7 @@ yarn info:networks
|
|
|
194
194
|
|
|
195
195
|
This will show you all supported networks and their corresponding RPC endpoints.
|
|
196
196
|
|
|
197
|
-
### Deploy to Other Network
|
|
197
|
+
### Deploy to Other Network (Non-Orbit Chains)
|
|
198
198
|
|
|
199
199
|
Once configured, deploy to your target network:
|
|
200
200
|
|
|
@@ -208,6 +208,14 @@ yarn deploy --network <network>
|
|
|
208
208
|
- **Always keep your private key secure and never commit it to version control**
|
|
209
209
|
- Consider using environment variable management tools for production deployments
|
|
210
210
|
|
|
211
|
+
### Deploy to Orbit Chains
|
|
212
|
+
|
|
213
|
+
Before deploying, you would have to ensure that your `deployStylusContract` function on your `deploy.ts` function has the `isOrbit` value set to `true` (example provided in `deploy.ts`).
|
|
214
|
+
|
|
215
|
+
Your contract must have an `initialize()` function as the replacement for the constructor, since not all orbit chains support the constructor feature. Please leave it blank if you don't have any constructor.
|
|
216
|
+
|
|
217
|
+
> Make sure you handle initialization properly in your contract, meaning it should only be called once and functions should not run if contract is not initialized.
|
|
218
|
+
|
|
211
219
|
## Verify your contract (Highly Experimental)
|
|
212
220
|
|
|
213
221
|
<details>
|