Skip to Content
⚠️ Alert: Sylan is under active development—only trust contract/wallet addresses announced on our official channels; we will never DM you, ask for funds, or run surprise airdrops/presales.
DeployTestnet

Deploy — Testnet (Polygon Amoy)

This guide gets Sylan’s contracts live on Polygon Amoy (80002), wires modules together, and performs a smoke test. It assumes you’re using Node 18+, pnpm, and Hardhat (or Foundry with equivalent steps). Final addresses must be copied to Architecture → Addresses & ABIs.

All core contracts are UUPS proxies. Always interact with the proxy addresses.


0) Prerequisites

  • Wallet with Amoy MATIC for gas (fund a deployer and a test user)
  • RPC URL for Amoy (e.g., Alchemy/Infura/Ankr)
  • pnpm, hardhat, typescript in your dev env

Install deps:

pnpm i

1) Environment

Create .env at repo root:

# Deployer PRIVATE_KEY=0xabc... # test key only # Polygon Amoy AMOY_RPC_URL=https://polygon-amoy.g.alchemy.com/v2/xxxxxxxx POLYGONSCAN_API_KEY=xxxxxxxx # Optional: initial params PLATFORM_TREASURY=0x1111111111111111111111111111111111111111 NODE_POOL=0x2222222222222222222222222222222222222222 TREASURY=0x3333333333333333333333333333333333333333

Hardhat config (example network stanza):

networks: { amoy: { url: process.env.AMOY_RPC_URL!, accounts: [process.env.PRIVATE_KEY!], chainId: 80002, }, }

2) Build & test locally

pnpm hardhat compile pnpm hardhat test

  1. SylanToken (ERC‑20, UUPS)
  2. EventLogger (UUPS)
  3. NodeRegistry (UUPS)
  4. APIEscrow (UUPS)
  5. APIConsensus (UUPS)
  6. AccessRegistry (UUPS)
  7. SylanStaking (optional, UUPS)
  8. SylanVesting (optional, non‑upgradeable)
  9. PresaleContract (optional, UUPS)

If you use a single script, deploy in this order and then wire addresses (next step).


4) Wiring (post‑deploy)

Run an admin script (or Hardhat tasks) to connect modules:

// pseudo‑code outline escrow.setPlatformTreasury(PLATFORM_TREASURY) escrow.setNodePool(NODE_POOL) escrow.setAccessRegistry(accessRegistry.address) escrow.setApiConsensus(consensus.address) escrow.setNodeRegistry(nodeRegistry.address) consensus.setQuorum(3) // example consensus.setRequestExpiryGraceMs(120_000) // 2 minutes accessRegistry.setApiEscrow(escrow.address) accessRegistry.setApiConsensus(consensus.address) accessRegistry.setNodeRegistry(nodeRegistry.address) accessRegistry.setMaxRequestExpiryMs(60_000) // 60s cap nodeRegistry.setTreasury(TREASURY) nodeRegistry.setNodePool(NODE_POOL) nodeRegistry.setSlashDistribution(5000, 4000, 1000) // 50/40/10 bps

Grant roles:

// If staking will mint rewards await sylanToken.grantRole(MINTER_ROLE, sylanStaking.address) // If staking won’t mint, pre‑fund rewardSource and set allowance

Use a multisig as owner where possible, even on testnet.


5) Verify on Polygonscan

pnpm hardhat verify --network amoy <impl_or_proxy_addr> <constructor/initializer args if any>
  • For UUPS proxies, verify implementation contracts and then mark the proxy as an EIP‑1967 proxy if your explorer supports it.

6) Seed test data

6.1 Fund testers with SYL

// From deployer/admin await sylanToken.mint("0xTester", ethers.parseUnits("100000", 18))

6.2 Register a sample API

const apiId = ethers.id("sample:price-feed:v1") // 32‑byte id await accessRegistry.registerApi( apiId, providerOwner, providerSigner, /*seqMonotonic=*/true, /*maxSkewMs=*/ 5000, /*maxTtlMs=*/ 60000, { accessType: 1, // PayPerCall price: ethers.parseUnits("12", 18), duration: 0, // PPC callLimit: 0, active: true, } ) await accessRegistry.setDescriptor(apiId, "ipfs://CID", "0xcontenthash...")

6.3 Register a node (optional for eligibility)

await sylanToken.approve(nodeRegistry, ethers.parseUnits("1000",18)) await nodeRegistry.registerAndStake(ethers.parseUnits("1000",18), testerPayout, "node‑amoy‑1")

7) Smoke test (PPC)

  1. Approve & lock
// tester wallet await sylanToken.approve(escrow, ethers.parseUnits("12",18)) const payload = { path: "/v1/price", query: { symbol: "BTC" } } const requestHash = keccak256(toHex(JSON.stringify(payload))) const expiresAtMs = BigInt(Date.now() + 60_000) const tx = await escrow.lockForCall(apiId, requestHash, expiresAtMs) const receipt = await tx.wait()
  1. Submit snapshots (node)
// Node submits provider‑signed Snapshot via consensus.submitSnapshot(...)
  1. Finalize → settle
  • Watch APIConsensus.RequestFinalized then APIEscrow.Settled.
  • Check balances with escrow.withdrawableOf(account); call withdraw().

8) Upgrade rehearsal (optional)

  • Deploy v2 implementations to Amoy.
  • Execute upgradeToAndCall with a reinitialize(2) payload on a non‑critical contract.
  • Confirm state preservation and new behavior.

Troubleshooting

  • Insufficient allowance/approve: ensure SYL approve (or permit) occurred before lockForCall/purchaseSubscription.
  • revert BPS sum: provider/node/platform BPS must sum to 10,000 when setting fees.
  • InactiveAPI: confirm AccessRegistry.isApiActive(apiId) is true.
  • Signer 0x0: if signer timelock is enabled, providerSignerOf(apiId) returns 0x0 until the window elapses.
  • Proxy verification: verify implementation first; explorers then recognize the proxy automatically.

Copy‑paste task list

  • Fund deployer & tester with Amoy MATIC
  • Set .env (RPC, PRIVATE_KEY, API keys)
  • Deploy in order (Token → Logger → NodeRegistry → Escrow → Consensus → Registry → optional contracts)
  • Wire addresses & parameters
  • Verify on Polygonscan
  • Seed: mint SYL, register API, stake a node
  • Smoke test PPC flow
Last updated on