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
  • MultiAccount Contract Functions
  • Initialization and Setup
  • initialize()
  • Account Management
  • addAccount()
  • editAccountName()
  • depositForAccount()
  • depositAndAllocateForAccount()
  • withdrawFromAccount()
  • Access Control
  • delegateAccess()
  • delegateAccesses()
  • Configuration and Address Management
  • setAccountImplementation()
  • setSymmioAddress()
  • Pausable Functionality
  • pause()
  • unpause()
  • Internal and Utility Functions
  • _deployPartyA()
  • _deployContract()
  • _call()
  • View Functions
  • getAccountsLength()
  • getAccounts()
  1. Protocol Architecture
  2. Technical Documentation
  3. Contract Docs
  4. Contracts Documentation 0.8.2

MultiAccount

In order to place trades using a SYMM frontend solution or otherwise, it's necessary to create a sub-account using a MultiAccount contract that is whitelisted to interact with the hedger. Users are required to provide a name as an input parameter when they create a sub-account. All positions on a sub-account are in CROSS, but positions between sub-accounts are ISOLATED.

MultiAccount Contract Functions

Initialization and Setup

initialize()

Initializes the MultiAccount contract with roles and addresses necessary for operation.

    function initialize(address admin, address symmioAddress_, bytes memory accountImplementation_) public initializer {
        __Pausable_init();
        __AccessControl_init();

        _grantRole(DEFAULT_ADMIN_ROLE, admin);
        _grantRole(PAUSER_ROLE, admin);
        _grantRole(UNPAUSER_ROLE, admin);
        _grantRole(SETTER_ROLE, admin);
        accountsAdmin = admin;
        symmioAddress = symmioAddress_;
        accountImplementation = accountImplementation_;
    }
  • Parameters:

    • admin: The administrator's address who will have default and control roles.

    • symmioAddress_: Address of the Symmio platform to interact with.

    • accountImplementation_: Bytecode for the account implementation to be used (SymmioPartyA).

Account Management

addAccount()

Creates a new sub-account for a user with a specified name.

    function addAccount(string memory name) external whenNotPaused {
        address account = _deployPartyA();
        indexOfAccount[account] = accounts[msg.sender].length;
        accounts[msg.sender].push(Account(account, name));
        owners[account] = msg.sender;
        emit AddAccount(msg.sender, account, name);
    }

Parameters:

  • name: Name of the sub-account.

Emits: AddAccount event upon successful creation.

editAccountName()

Allows the owner to change the name of an existing sub-account.

    function editAccountName(address accountAddress, string memory name) external whenNotPaused {
        uint256 index = indexOfAccount[accountAddress];
        accounts[msg.sender][index].name = name;
        emit EditAccountName(msg.sender, accountAddress, name);
    }

Parameters:

  • accountAddress: Address of the account to rename.

  • name: New name for the account.

Emits: EditAccountName event.

depositForAccount()

Deposits funds into a sub-account from the owner's balance.

    function depositForAccount(address account, uint256 amount) external onlyOwner(account, msg.sender) whenNotPaused {
        address collateral = ISymmio(symmioAddress).getCollateral();
        IERC20Upgradeable(collateral).safeTransferFrom(msg.sender, address(this), amount);
        IERC20Upgradeable(collateral).safeApprove(symmioAddress, amount);
        ISymmio(symmioAddress).depositFor(account, amount);
        emit DepositForAccount(msg.sender, account, amount);
    }

Parameters:

  • account: Address of the sub-account.

  • amount: Amount to deposit.

Emits: DepositForAccount event.

depositAndAllocateForAccount()

Deposits funds into a sub-account and allocates them for trading.

    function depositAndAllocateForAccount(address account, uint256 amount) external onlyOwner(account, msg.sender) whenNotPaused {
        address collateral = ISymmio(symmioAddress).getCollateral();
        IERC20Upgradeable(collateral).safeTransferFrom(msg.sender, address(this), amount);
        IERC20Upgradeable(collateral).safeApprove(symmioAddress, amount);
        ISymmio(symmioAddress).depositFor(account, amount);
        uint256 amountWith18Decimals = (amount * 1e18) / (10 ** IERC20Metadata(collateral).decimals());
        bytes memory _callData = abi.encodeWithSignature("allocate(uint256)", amountWith18Decimals);
        innerCall(account, _callData);
        emit DepositForAccount(msg.sender, account, amount);
        emit AllocateForAccount(msg.sender, account, amountWith18Decimals);
    }

Parameters:

  • account: Address of the sub-account.

  • amount: Amount to deposit and allocate.

Emits: DepositForAccount and AllocateForAccount events.

withdrawFromAccount()

Withdraws funds from a sub-account back to the owner's address.

    function withdrawFromAccount(address account, uint256 amount) external onlyOwner(account, msg.sender) whenNotPaused {
        bytes memory _callData = abi.encodeWithSignature("withdrawTo(address,uint256)", owners[account], amount);
        emit WithdrawFromAccount(msg.sender, account, amount);
        innerCall(account, _callData);
    }

Parameters:

  • account: Address of the sub-account.

  • amount: Amount to withdraw.

Emits: WithdrawFromAccount event.

Access Control

delegateAccess()

Allows the owner of a sub-account to delegate control over specific functions to another address.

    function delegateAccess(address account, address target, bytes4 selector, bool state) external onlyOwner(account, msg.sender) {
        require(target != msg.sender && target != account, "MultiAccount: invalid target");
        emit DelegateAccess(account, target, selector, state);
        delegatedAccesses[account][target][selector] = state;
    }

Parameters:

  • account: Address of the sub-account.

  • target: Address to which access is delegated.

  • selector: Function selector for which access is granted.

  • state: Boolean to enable or disable access. true sets the delegation state to enabled, allowing the delegate to call the specified function on behalf of the sub-account

Emits: DelegateAccess event.

delegateAccesses()

Batch version of delegateAccess for multiple function selectors.

    function delegateAccesses(address account, address target, bytes4[] memory selector, bool state) external onlyOwner(account, msg.sender) {
        require(target != msg.sender && target != account, "MultiAccount: invalid target");
        for (uint256 i = selector.length; i != 0; i--) {
            delegatedAccesses[account][target][selector[i - 1]] = state;
            emit DelegateAccess(account, target, selector[i - 1], state);
        }
    }

Parameters:

  • account, target, selector[], and state as in delegateAccess.

Emits: DelegateAccess event for each selector.

Configuration and Address Management

setAccountImplementation()

Sets new account implementation bytecode.

    function setAccountImplementation(bytes memory accountImplementation_) external onlyRole(SETTER_ROLE) {
        emit SetAccountImplementation(accountImplementation, accountImplementation_);
        accountImplementation = accountImplementation_;
    }

Parameters:

  • accountImplementation_: New bytecode for account implementation.

Emits: SetAccountImplementation event.

setSymmioAddress()

Updates the address of the Symmio platform.

    function setSymmioAddress(address addr) external onlyRole(SETTER_ROLE) {
        emit SetSymmioAddress(symmioAddress, addr);
        symmioAddress = addr;
    }

Parameters:

addr: New address for the Symmio platform.

Emits: SetSymmioAddress event.

Pausable Functionality

pause()

Pauses all pausable actions in the contract, preventing execution. Only callable by addresses with the PAUSER_ROLE.

    function pause() external onlyRole(PAUSER_ROLE) {
        _pause();
    }

unpause()

Resumes all actions in the contract after being paused. Only callable by addresses with the UNPAUSER_ROLE.

    function unpause() external onlyRole(UNPAUSER_ROLE) {
        _unpause();
    }

Internal and Utility Functions

_deployPartyA()

Deploys a new sub-account using the current account implementation.

    function _deployPartyA() internal returns (address account) {
        bytes32 salt = keccak256(abi.encodePacked("MultiAccount_", saltCounter));
        saltCounter += 1;

        bytes memory bytecode = abi.encodePacked(accountImplementation, abi.encode(accountsAdmin, address(this), symmioAddress));
        account = _deployContract(bytecode, salt);
        return account;
    }

Returns: Address of the newly deployed account.

_deployContract()

Internal function to deploy contracts using the create2 opcode.

    function _deployContract(bytes memory bytecode, bytes32 salt) internal returns (address contractAddress) {
        assembly {
            contractAddress := create2(0, add(bytecode, 32), mload(bytecode), salt)
        }
        require(contractAddress != address(0), "MultiAccount: create2 failed");
        emit DeployContract(msg.sender, contractAddress);
        return contractAddress;
    }

Parameters:

  • bytecode: Compiled bytecode of the contract.

  • salt: Salt used for create2 to determine the address.

Returns: Address of the deployed contract.

_call()

Internal function to invoke methods on other contracts.

    function _call(address account, bytes[] memory _callDatas) public whenNotPaused {
        bool isOwner = owners[account] == msg.sender;
        for (uint8 i; i < _callDatas.length; i++) {
            bytes memory _callData = _callDatas[i];
            if (!isOwner) {
                require(_callData.length >= 4, "MultiAccount: Invalid call data");
                bytes4 functionSelector;
                assembly {
                    functionSelector := mload(add(_callData, 0x20))
                }
                require(delegatedAccesses[account][msg.sender][functionSelector], "MultiAccount: Unauthorized access");
            }
            innerCall(account, _callData);
        }
    }

Parameters:

  • account: Account from which the call is made.

  • _callDatas[]: Array of call data to be executed.

Executes multiple calls in a single transaction if authorized.

View Functions

getAccountsLength()

Returns the number of accounts owned by a user.

    function getAccountsLength(address user) external view returns (uint256) {
        return accounts[user].length;
    }

Parameters:

  • user: Address of the user.

Returns: Number of accounts.

getAccounts()

Retrieves a list of sub-accounts owned by a user.

    function getAccounts(address user, uint256 start, uint256 size) external view returns (Account[] memory) {
        uint256 len = size > accounts[user].length - start ? accounts[user].length - start : size;
        Account[] memory userAccounts = new Account[](len);
        for (uint256 i = start; i < start + len; i++) {
            userAccounts[i - start] = accounts[user][i];
        }
        return userAccounts;
    }

Parameters:

  • user: Owner's address.

  • start: Start index for pagination.

  • size: Number of accounts to return.

Returns: Array of Account structs.

PreviousView FacetNextPartyA

Last updated 11 months ago