LogoLogo
  • Overview
    • Introduction
    • Table of Contents
  • Token Information
    • Symmio Foundation
  • Protocol Architecture
    • Protocol Introduction
    • Technical Documentation
      • Building an Application with SYMM
        • Introduction and Diamond Explainer
        • Querying Info from the SYMM Diamond
        • MultiAccount
        • Creating an Account and Depositing Funds
        • Sending a Quote
        • Closing a Quote
        • Instant Trading
          • Instant Login (EOA)
          • Instant Login (Account Abstraction)
          • Sending a Quote (Instant Open)
          • Sending a Quote (Instant Close)
        • Frequently Used Queries
      • Solver Docs
        • Solver Docs (github)
        • Solver Implementation Guide (High Level Overview)
        • Building a Solver on SYMMIO
          • 1. Intent Creation
          • 2. Seeing the Intent
          • 3. Hedging Off-Chain
          • 4. Opening/Closing a Position On-Chain
          • Creating the APIs
            • GET Contract Symbols
            • GET Open Interest
            • GET Notional Cap
            • GET Price Range
            • GET Error Codes
            • GET Get Locked Params
            • GET Get Funding Info
            • POST Position State
          • Solver Flow Summary Example
          • Recommended Architecture for Solvers
          • Glossary
        • Conditional Orders Handler
        • Rasa Solver TP/SL Implementation
        • Instant Trading
          • Instant Trading (Solvers)
          • Rasa Instant Trading Implementation
          • Instant Trading Condition Checks
        • Fetching Gas Prices Script
        • How to Add a Market as a Solver
        • Verifying Account Abstracted Instant Actions (ERC-4337)
      • Frontend Docs
        • Setting up a Frontend with SYMMIO
        • Frontend SDK Setup Guide
        • MultiAccount Deployment Guide
        • Instant Trading (Frontends)
          • Account Abstracted Instant Actions (Frontends)
        • Implement a Trading Bot on Symmio (OLD)
          • Setup
          • Creating a Sub-Account
          • Minting Collateral Tokens (Optional)
          • Depositing and Allocating Tokens
          • Obtaining Muon Signatures
          • Sending a Quote
          • Monitoring Price for Execution
      • Contract Docs
        • SYMMIO CORE v0.82
        • Contracts Documentation 0.8.2
          • Main Flow
          • The SYMM Diamond
          • Facets
            • Account Facet
            • Control Facet
            • Funding Rate Facet
            • PartyA Facet
            • PartyB Facet
            • Liquidation Facet
            • View Facet
          • MultiAccount
            • PartyA
            • PartyB
          • SYMM App (Muon)
            • LibMuon
            • MuonStorage
        • Contracts Documentation 0.8.3
          • Facets
            • Control Facet
            • Account Facet
            • PartyA Facet
            • PartyB Facet
            • View Facet
            • Bridge Facet
            • Liquidation Facet (Implementation)
          • Modified Events
          • New Events
          • MuonStorage
        • Contracts Documentation 0.8.4
          • Main Flow (0.8.4)
          • The SYMM Diamond (0.8.4)
          • Facets
            • Account Facet (0.8.4)
            • Bridge Facet (0.8.4)
            • Control Facet (0.8.4)
            • Force Actions Facet (0.8.4)
            • Funding Rate Facet (0.8.4)
            • Liquidations Facet (0.8.4)
            • PartyA Facet (0.8.4)
            • PartyB Group Actions Facet (0.8.4)
            • PartyB Quote Actions Facet (0.8.4)
            • PartyB Position Actions Facet (0.8.4)
            • Settlement Facet (0.8.4)
            • View Facet (0.8.4)
          • MultiAccount (0.8.4)
            • SymmioPartyA
            • SymmioPartyB
          • SYMM App (Muon)
            • LibMuon (0.8.4)
            • MuonStorage (0.8.4)
      • Contract Addresses / Solver Endpoints
        • Mantle
        • Mode
        • IOTA
        • Base
        • BSC
        • Arbitrum
        • Polygon
        • Berachain
        • Solver Endpoints and Addresses
          • Perps Hub
          • Rasa Capital
          • Zenith
      • How to Query our Contracts
      • Muon API Queries
      • Solver Error Codes
      • Interacting with SYMMIO Contracts
    • Protocol higher level architecture
      • 12-Hour Fraud Proof Window
      • PartyB
      • Solver Settings
      • Max Leverage
      • Maintenance Margin (CVA) Calculations
    • Symmio Whitepaper
  • Building on Symmio
    • Builders introduction
    • Solving for Symmio
      • Solver documentation
      • Solver - Example Flow
    • Trading Fees
      • Perps - Settlement Costs
      • Pair Trading - Settlement costs
    • Exchanges (Frontends)
      • Frontend Introduction
      • SDK - SYMM client
      • Trade on Symmio
  • Legal & Brand & Security
    • Security (Audits / Bugbounty)
      • Bug bounty / Coverage
        • How to contact ?
      • Audits
        • SYMM - V0.8 - 0.81
          • Sherlock Audit - Jun 15, 2023
          • Smart State - Jul 2, 2023
        • SYMM - 0.82
          • Sherlock Audit -Aug 30, 2023
        • SYMM - 0.83
          • Sherlock Audit - Jun 17, 2024
        • SYMM - 0.84
          • Sherlock Audit - Oct 3, 2024
        • Vaults
          • Sherlock Audit - Jan 2, 2024
    • Terms of Service & Licensing
      • TRADEMARK & COPYRIGHT NOTICE
      • CONTACT US
      • TERMS OF SERVICE
      • FRONTEND LICENSE
        • Frontend Modifications
        • Frontend Use Grants
      • CONTRACT LICENSE
        • Contract Use Grants
        • Contract Modifications
    • Brand - Assets Logos
Powered by GitBook
LogoLogo

All rights to the people (c) 2023 Symmetry Labs A.G.

On this page
  • Step 1: Setting up Hardhat
  • Step 2: Adding the MultiAccount Contract to our Project
  • Step 3: Installing Required Packages
  • Step 4: Saving the Deployed Address
  • Step 5: Installing Dependencies for the Deployment Script
  • Step 6: Writing the Deployment Script
  • Step 7: Configuring the Deployment Script for Specified Chains
  • Step 8: Deploying the MultiAccount contract
  1. Protocol Architecture
  2. Technical Documentation
  3. Frontend Docs

MultiAccount Deployment Guide

PreviousFrontend SDK Setup GuideNextInstant Trading (Frontends)

Last updated 5 months ago

This document outlines the required steps and responsibilities for deploying the MultiAccount contract.

  1. Responsibility and Security The full responsibility for the deployment and ongoing management of the MultiAccount contract lies with the deploying entity. To ensure the integrity and security of the contract, please take the following actions:

    • Conduct thorough audits of the contract code.

    • Implement robust security checks.

    • Ensure regular maintenance and monitoring of the deployed contract.

  2. Deployment of Latest Version It is essential to deploy the latest version of the MultiAccount contract. The most current version can be found at the following link:

Please note that the MultiAccount contract available in this repository is a sample code. You are free to modify or customize the code to meet your specific requirements. However, be aware that any modifications or changes to the contract may extend the time required for the registration process, as the Symmio team will need to thoroughly review and approve the changes.

  1. Transfer of Admin Roles and ProxyAdmin Ownership Upon successful deployment, the following steps must be completed to ensure secure management of the contract:

    • Transfer the admin roles to the appropriate entity.

    • Transfer ownership of the ProxyAdmin to a 3-day timelock contract for added security.

These measures are necessary to safeguard the contract against unauthorized access or modifications.

  1. Proposal to Symmio Team After deploying the contract and completing the necessary security measures, a formal proposal must be submitted to the Symmio team. The proposal should request that the deployed MultiAccount contract address be registered in the Symmio Core Contracts. If any modifications have been made to the original sample contract, please note that the registration process may take longer due to the required review of the changes by the Symmio team.

Prerequisites

  • Install Node.js and npm.

  • Install Hardhat in your project directory: npm install --save-dev hardhat

  • Install Typescript and ts-node: npm install --save-dev typescript ts-node

Step 1: Setting up Hardhat

  1. Initialize a new Hardhat project:

    npx hardhat init
  2. Follow the prompts to create a sample project.

To run a TypeScript deployment script with Hardhat, you'll need to make sure your environment is set up correctly for TypeScript execution.

TypeScript Configuration:

Ensure you have a tsconfig.json file in your project root. This file configures options for TypeScript in your project. Hardhat automatically generates this for you if you initialize your project with TypeScript support:

{
  "compilerOptions": {
    "target": "es2020",
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "resolveJsonModule": true,
    "noErrorTruncation": true
  }
}

Step 2: Adding the MultiAccount Contract to our Project

Once you have your TypeScript configuration ready, the next step in setting up your deployment is to incorporate the MultiAccount contract and its essential interfaces. You'll need to place the contracts and its associated interfaces within the /contracts directory of your project. These components are available in the Symmio's protocol-core GitHub repository, within the /contracts/multiAccount and /contracts/interfaces directories. Ensure the following files are added to your project:

Contracts: (/contracts/multiAccount)

  • MultiAccount.sol: The primary contract for managing multiple accounts.

  • SymmioPartyA.sol: This is used for deploying user sub-accounts through the CREATE-2 opcode, offering a more efficient and flexible account creation process.

Interfaces: (/contracts/interfaces)

  • IMultiAccount.sol: Interface for the MultiAccount contract.

  • ISymmio.sol: SYMMIO protocol interface.

  • ISymmioPartyA.sol: Interface specific to the SymmioPartyA contract.

Step 3: Installing Required Packages

The MultiAccount.sol contract imports from earlier versions of Openzeppelin's libraries. We'll install @openzeppelin/contracts@^4.9.0 and @openzeppelin/contracts-upgradeable@^4.7.3

Open your terminal or command prompt, navigate to your project's root directory and run the following commands:

  1. Install OpenZeppelin Contracts:

    npm install @openzeppelin/contracts@^4.9.0

    This command installs the OpenZeppelin Contracts package at version 4.9.0 or the latest minor version within the 4.9.x range.

  2. Install OpenZeppelin Contracts-Upgradeable:

    npm install @openzeppelin/contracts-upgradeable@^4.7.3

After running these commands, your package.json file will be automatically updated to reflect these dependencies and their versions under the dependencies section. It should look something like this:

"dependencies": {
  "@openzeppelin/contracts": "^4.9.0",
  "@openzeppelin/contracts-upgradeable": "^4.7.3",
}

Step 4: Saving the Deployed Address

After successful deployment of the MultiAccount and SymmioPartyA contracts, it's helpful to track the deployed contract addresses for future deployments. We'll incorporate a utility module specifically designed for saving and loading these critical addresses. This approach ensures that when the MultiAccount contract is initialized, it can readily access the protocol address (symmioAddress) and the bytecode for the SymmioPartyA contract. The /utilty/file.ts script handles this for us, and we'll incorporate it into our main deployment script.

import fs from "fs"

export type Addresses = {
  symmioAddress?: string,
  collateralAddress?: string,
  multiAccountAddress?: string,
  hedgerProxyAddress?: string,
  MulticallAddress?: string,
}

export function loadAddresses(): Addresses {
  let output: Addresses = {}
  if (fs.existsSync("./output/addresses.json")) {
    output = JSON.parse(fs.readFileSync("./output/addresses.json", "utf8"))
  } else {
    if (!fs.existsSync("./output"))
      fs.mkdirSync("./output")
    output = {}
    fs.writeFileSync("./output/addresses.json", JSON.stringify(output))
  }
  return output
}

export function saveAddresses(content: Addresses): void {
  if (!fs.existsSync("./output/addresses.json")) {
    if (!fs.existsSync("./output"))
      fs.mkdirSync("./output")
  }
  fs.writeFileSync("./output/addresses.json", JSON.stringify(content))
}
{
    "symmioAddress":"",
    "collateralAddress":"",
    "multiAccountAddress":"",
    "partyBAddress":"",
    "MulticallAddress":""
}

Step 5: Installing Dependencies for the Deployment Script

Before moving on to the actual deployment, we'll be installing and using hardhat-ethers and hardhat-upgrades. The ethers.js library is designed to provide a comprehensive yet compact toolkit for interacting with the Ethereum Blockchain and its vast ecosystem, serving as the foundation of our deployment scripts. hardhat-upgrades, is a plugin aimed at streamlining the deployment and upgrade process of smart contracts through proxies.

Run this command in the command prompt:

npm install @nomiclabs/hardhat-ethers@^2.2.3 @openzeppelin/hardhat-upgrades@^1.21.0 ethers@^5.7.2

Step 6: Writing the Deployment Script

First import the dependencies we installed in Step 4:

import { ethers, run, upgrades } from "hardhat"

Then import the file utility for loading and saving addresses:

import { Addresses, loadAddresses, saveAddresses } from "../utils/file"

The deployment script should perform the following:

  1. Getting Signers: The script starts by retrieving the list of signers (accounts) available from the node it's connected to, using Hardhat's ethers plugin. It assumes the first account (deployer) is the one to be used for deploying the contracts. The private key for the deployer account is declared in hardhat.config.ts

  2. Loading Contract Deployments: It attempts to load previously deployed addresses from a function loadAddresses()

  3. Contract Factory for SymmioPartyA: It creates a contract factory for SymmioPartyA. This factory is used to deploy new instances of the contract.

  4. Deploying MultiAccount as Upgradeable: It proceeds to deploy MultiAccount in an upgradeable manner using OpenZeppelin's upgrades plugin. The deployment uses a proxy pattern where the actual contract logic (implementation) and state are separated. The contract initializes with:

  • admin : the admin address.

  • symmioAddress: the SYMMIO contract address.

  • accountImplementation_: the bytecode of SymmioPartyA

  1. Logging Deployment Addresses: After deployment, it logs the addresses related to the deployed upgradeable contract, including the proxy address, the admin address and the implementation address.

  2. Saving Addresses: The script then updates the addresses.json with the new multiAccountAddress for reference in future deployments.

  3. Verification Process: It attempts to verify the deployed contract on a blockchain explorer. The verification process is delayed by 15 seconds before using Hardhat's verify:verify task to submit verification information.

  4. Error Handling and Script Completion: The script ends with a basic structure to handle promise resolution, logging any errors encountered and exiting the process accordingly.

deployMultiAccount.ts
async function main() {
	const [deployer] = await ethers.getSigners()

	console.log("Deploying contracts with the account:", deployer.address)
	let deployedAddresses: Addresses = loadAddresses()
	console.log("Deployed Addresses:", deployedAddresses);

	const SymmioPartyA = await ethers.getContractFactory("SymmioPartyA")

	const Factory = await ethers.getContractFactory("MultiAccount")
	console.log("Factory Deployed. ");

	const admin = process.env.ADMIN_PUBLIC_KEY
	const contract = await upgrades.deployProxy(Factory, [
		admin, deployedAddresses.symmioAddress,
		SymmioPartyA.bytecode,
	], { 
		initializer: "initialize",
	  })
	await contract.deployed()
	console.log("Contract Deployed. ");


	const addresses = {
		proxy: contract.address,
		admin: await upgrades.erc1967.getAdminAddress(contract.address),
		implementation: await upgrades.erc1967.getImplementationAddress(
		  contract.address,
		),
	}
	console.log(addresses)

	deployedAddresses.multiAccountAddress = contract.address
	saveAddresses(deployedAddresses)

	try {
		console.log("Verifying contract...")
		await new Promise((r) => setTimeout(r, 15000))
		await run("verify:verify", { address: addresses.implementation })
		console.log("Contract verified!")
	} catch (e) {
		console.log(e)
	}
}

main()
  .then(() => process.exit(0))
  .catch((error) => {
	  console.error(error)
	  process.exit(1)
  })

Step 7: Configuring the Deployment Script for Specified Chains

Deploying the MultiAccount contract requires the deployment account's private and public keys. Due to their sensitive nature, its important to integrate dotenv with our script. dotenv facilitates the safe storage and access of private variables, like the deployment account's keys, through an environment file (*.env).

npm install dotenv

Create a .env File

In the root of your project, create a file named .env. Inside this file, you'll define environment variables. For example:

.env.example
ADMIN_PUBLIC_KEY=
POLYGON_API_KEY=
PRIVATE_KEY=""
PRIVATE_KEYS_STR=""
ADMIN_PUBLIC_KEY=""

In our config file, we'll declare these as:

const privateKey: string | undefined = process.env.PRIVATE_KEY
if (!privateKey)
	throw new Error("Please set your PRIVATE_KEY in a .env file")

const privateKeysStr: string | undefined = process.env.PRIVATE_KEYS_STR
const privateKeyList: string[] = privateKeysStr?.split(",") || []

const mantleAPIKey: string = process.env.MANTLE_API_KEY || ""
const ftmAPIKey: string = process.env.FTM_API_KEY || ""
const bnbApiKey: string = process.env.BNB_API_KEY || ""
const baseApiKey: string = process.env.BASE_API_KEY || ""
const polygonApiKey: string = process.env.POLYGON_API_KEY || ""
const zkEvmApiKey: string = process.env.ZKEVM_API_KEY || ""
const opBnbApiKey: string = process.env.OPBNB_API_KEY || ""

const hardhatDockerUrl: string | undefined = process.env.HARDHAT_DOCKER_URL || ""

Networks Configuration

Each network has specific settings that tell Hardhat where to deploy the contracts, which accounts to use, and any network-specific options like gas prices. Here are examples for various chains:

networks: {
	mantle: {
		url: "https://1rpc.io/mantle",
		accounts: [ privateKey ],
	},
	
}, //other networks...
  • URL: Each network has a url that specifies the JSON-RPC endpoint to connect to. This is essential for deploying to that specific network.

  • Accounts: Specifies which accounts to use for transactions on the network. This can be a list of private keys or a single key.

Explorer Configuration

This part of the configuration is essential for verifying contract deployments on different networks, allowing you to interact with your contracts through blockchain explorers.

etherscan: {
	apiKey: {
		mantle: mantleAPIKey,
		fantom: ftmAPIKey,
		bnb: bnbApiKey,
		base: baseApiKey,
		polygon: polygonApiKey,
		zkEvm: zkEvmApiKey,
		opbnb: opBnbApiKey,
	},
	customChains: [
		{
			network: "mantle",
			chainId: 5000,
			urls: {
				apiURL: "https://explorer.mantle.xyz/api",
				browserURL: "https://explorer.mantle.xyz"
			}
		},
		// other networks...
	],
},
  • API Key: Each entry under apiKey is crucial for authentication when using the Etherscan-like services to verify contracts. The API key can be obtained from creating an account with an explorer.

  • Custom Chains: Configuration for custom networks (not standard like Ethereum Mainnet or Ropsten) to ensure that the Hardhat Etherscan plugin knows how to interact with these networks' explorers.

Step 8: Deploying the MultiAccount contract

To run the deployment script, enter the following command in the terminal, where {chain} is the desired deployment chain:

npx hardhat run scripts/deployMultiAccount.ts --network {chain}

Troubleshooting

It might be necessary to set a gasPrice to ensure timely deployments. This can be customized in the hardhat config file:

{chain}: {3
      url: "",
      accounts: [ privateKey ],
      gasPrice: ,

To initiate our first deployment, create an addresses.json file that contains the contract addresses needed to initialize the MultiAccount contract. Use the to populate the fields according to the specific chain you'd like to deploy on.

An example hardhat-config.ts file can be found at . Ensure you install the necessary dependency versions if you're using this method.

MultiAccount Contract
contract addresses
this Github repository