GithubHelp home page GithubHelp logo

marginswap-core's Introduction

marginswap-core

Core contracts for marginswap functionality

Install

Install dependencies:

yarn install
git clone [email protected]:marginswap/core-abi.git build

Place a private key file in your home folder ~/.marginswap-secret. If you want it to match up with your wallet like MetaMask, create the account in your wallet, copy the private key and paste it into the file.

Rationale

MarginRouter is the entry point for most traders to interact with the protocol. Lending and CrossMarginTrading, as well as their ancilliary superclasses are the lending and borrowing sides of the system.

We have gone for a relatively modular approach which should make it easy for governance to switch out / update parts of the logic. There is a central registry for roles. Also, funds are kept at arm's length from functionality.

The DependencyController contract provides cache invalidation and tracking of roles and relationships between contracts, central verification of integrity of our ownership structure as well as additonal safeguards for governance-approved protocol-wide actions.

There is to be no constantly-updating oracle or gas-costly block-wise auctions for token holders.

marginswap-core's People

Contributors

koochr avatar vaer-k avatar werg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

marginswap-core's Issues

A very simple dApp for liquidity staking

When users deposit liquidity into the trading pair USDC - MFI on uniswap they are minted and sent a different "liquidity" token which represents their share of the entire liquidity pool, in the case of the USDC - MFI trading pair, it's this token contract.

We want to incentivize people to do so, as such they can take those tokens and deposit them into a contract which we will deploy, in order to then earn more of the MFI tokens. For this we need a frontend UI to help people deposit and withdraw.

I set up a repo here: https://github.com/marginswap/lp-incentive-interface

The app should:

  • Be a react/TS app
  • Run on netlify / JAMstack (I.e. static site generated by yarn build)
  • Using ethers.js

It should talk to the contract in contracts/LiquidityMiningReward.sol as well as a token which is at address 0x9d640080af7c81911d87632a7d09cc4ab6b133ac . I will provide a local deployment script later.

When a user goes to the website they will do the following:

  • Enter an amount of tokens in a input box.

  • Click one button which will call the function approve(address spender, uint256 amount) (interface spec) on the liquidity token contract, where the spender address will be the address of the LiquidityMiningReward contract.

  • Once that function call has been processed through the user's wallet (such as MetaMask) they will come back to the website and click another button which will deposit their liquidity tokens using the depositStake(uint256 amount) function in the mining reward contract

  • Later, when they want to withdraw, they will come back and be able to hit a button which calls withdrawStake() in the same contract.

image

Local test deployment

We want to translate the code in contracts/V1.sol into JS/TS based deployment scripts, probably using ether.js.
I think we want to use hardhat for (unit) testing the contracts, but we need to still have to find a way to run an ongoing local ethereum blockchain. This could be hardhat scripts (since hardhat doesn't have native migrations, or we could use etherlime.
Brownie would be the nicest, but probably not advisable since it's Python.
Here's a dump of my hardhat console session doing the kind of work I would do to translate V1.sol into JS:

// $ npx hardhat console
Welcome to Node.js v13.14.0.
Type ".help" for more information.
> ethers
{
  Contract: [Function: Contract] {
    getContractAddress: [Function (anonymous)],
    getInterface: [Function (anonymous)],
    isIndexed: [Function (anonymous)]
  },
  ContractFactory: [Function: ContractFactory] {
    fromSolidity: [Function (anonymous)],
    getInterface: [Function (anonymous)],
    getContractAddress: [Function (anonymous)],
    getContract: [Function (anonymous)]
  },
  BigNumber: [Function: BigNumber] {
    from: [Function (anonymous)],
    isBigNumber: [Function (anonymous)]
  },
  FixedNumber: [Function: FixedNumber] {
    fromValue: [Function (anonymous)],
    fromString: [Function (anonymous)],
    fromBytes: [Function (anonymous)],
    from: [Function (anonymous)],
    isFixedNumber: [Function (anonymous)]
  },
  Signer: [Function: Signer] { isSigner: [Function (anonymous)] },
  VoidSigner: [Function: VoidSigner],
  Wallet: [Function: Wallet] {
    createRandom: [Function (anonymous)],
    fromEncryptedJson: [Function (anonymous)],
    fromEncryptedJsonSync: [Function (anonymous)],
    fromMnemonic: [Function (anonymous)]
  },
  constants: {
    AddressZero: '0x0000000000000000000000000000000000000000',
    NegativeOne: BigNumber { _hex: '-0x01', _isBigNumber: true },
    Zero: BigNumber { _hex: '0x00', _isBigNumber: true },
    One: BigNumber { _hex: '0x01', _isBigNumber: true },
    Two: BigNumber { _hex: '0x02', _isBigNumber: true },
    WeiPerEther: BigNumber { _hex: '0x0de0b6b3a7640000', _isBigNumber: true },
    MaxUint256: BigNumber {
      _hex: '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
      _isBigNumber: true
    },
    HashZero: '0x0000000000000000000000000000000000000000000000000000000000000000',
    EtherSymbol: 'ฮž'
  },
  providers: {
    Provider: [Function: Provider] { isProvider: [Function (anonymous)] },
    getNetwork: [Function: getNetwork],
    BaseProvider: [Function: BaseProvider] {
      getFormatter: [Function (anonymous)],
      getNetwork: [Function (anonymous)]
    },
    Resolver: [Function: Resolver],
    AlchemyProvider: [Function: AlchemyProvider] {
      getWebSocketProvider: [Function (anonymous)],
      getApiKey: [Function (anonymous)],
      getUrl: [Function (anonymous)]
    },
    AlchemyWebSocketProvider: [Function: AlchemyWebSocketProvider],
    CloudflareProvider: [Function: CloudflareProvider] {
      getApiKey: [Function (anonymous)],
      getUrl: [Function (anonymous)]
    },
    EtherscanProvider: [Function: EtherscanProvider],
    FallbackProvider: [Function: FallbackProvider],
    IpcProvider: [Function: IpcProvider],
    InfuraProvider: [Function: InfuraProvider] {
      getWebSocketProvider: [Function (anonymous)],
      getApiKey: [Function (anonymous)],
      getUrl: [Function (anonymous)]
    },
    InfuraWebSocketProvider: [Function: InfuraWebSocketProvider],
    JsonRpcProvider: [Function: JsonRpcProvider] {
      defaultUrl: [Function (anonymous)],
      hexlifyTransaction: [Function (anonymous)]
    },
    JsonRpcSigner: [Function: JsonRpcSigner],
    NodesmithProvider: [Function: NodesmithProvider] {
      getApiKey: [Function (anonymous)],
      getUrl: [Function (anonymous)]
    },
    PocketProvider: [Function: PocketProvider] {
      getApiKey: [Function (anonymous)],
      getUrl: [Function (anonymous)]
    },
    StaticJsonRpcProvider: [Function: StaticJsonRpcProvider],
    UrlJsonRpcProvider: [Function: UrlJsonRpcProvider] {
      getApiKey: [Function (anonymous)],
      getUrl: [Function (anonymous)]
    },
    Web3Provider: [Function: Web3Provider],
    WebSocketProvider: [Function: WebSocketProvider] { defaultUrl: [Function (anonymous)] },
    Formatter: [Function: Formatter] {
      check: [Function (anonymous)],
      allowNull: [Function (anonymous)],
      allowFalsish: [Function (anonymous)],
      arrayOf: [Function (anonymous)]
    },
    isCommunityResourcable: [Function: isCommunityResourcable],
    isCommunityResource: [Function: isCommunityResource],
    showThrottleMessage: [Function: showThrottleMessage],
    getDefaultProvider: [Function: getDefaultProvider]
  },
  getDefaultProvider: [Function: getDefaultProvider],
  Wordlist: [Function: Wordlist] {
    check: [Function (anonymous)],
    register: [Function (anonymous)]
  },
  wordlists: {
    cz: LangCz { locale: 'cz' },
    en: LangEn { locale: 'en' },
    es: LangEs { locale: 'es' },
    fr: LangFr { locale: 'fr' },
    it: LangIt { locale: 'it' },
    ja: LangJa { locale: 'ja' },
    ko: LangKo { locale: 'ko' },
    zh: LangZh { locale: 'zh_cn' },
    zh_cn: LangZh { locale: 'zh_cn' },
    zh_tw: LangZh { locale: 'zh_tw' }
  },
  utils: {
    AbiCoder: [Function: AbiCoder],
    checkResultErrors: [Function: checkResultErrors],
    defaultAbiCoder: AbiCoder { coerceFunc: null },
    EventFragment: [Function: EventFragment] {
      from: [Function (anonymous)],
      fromObject: [Function (anonymous)],
      fromString: [Function (anonymous)],
      isEventFragment: [Function (anonymous)]
    },
    FormatTypes: {
      sighash: 'sighash',
      minimal: 'minimal',
      full: 'full',
      json: 'json'
    },
    Fragment: [Function: Fragment] {
      from: [Function (anonymous)],
      fromObject: [Function (anonymous)],
      fromString: [Function (anonymous)],
      isFragment: [Function (anonymous)]
    },
    FunctionFragment: [Function: FunctionFragment] {
      from: [Function (anonymous)],
      fromObject: [Function (anonymous)],
      fromString: [Function (anonymous)],
      isFunctionFragment: [Function (anonymous)]
    },
    Indexed: [Function: Indexed] { isIndexed: [Function (anonymous)] },
    Interface: [Function: Interface] {
      getAbiCoder: [Function (anonymous)],
      getAddress: [Function (anonymous)],
      getSighash: [Function (anonymous)],
      getEventTopic: [Function (anonymous)],
      isInterface: [Function (anonymous)]
    },
    LogDescription: [Function: LogDescription],
    ParamType: [Function: ParamType] {
      from: [Function (anonymous)],
      fromObject: [Function (anonymous)],
      fromString: [Function (anonymous)],
      isParamType: [Function (anonymous)]
    },
    TransactionDescription: [Function: TransactionDescription],
    getAddress: [Function: getAddress],
    getCreate2Address: [Function: getCreate2Address],
    getContractAddress: [Function: getContractAddress],
    getIcapAddress: [Function: getIcapAddress],
    isAddress: [Function: isAddress],
    base64: { decode: [Function: decode], encode: [Function: encode] },
    base58: BaseX {
      alphabet: '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz',
      base: 58,
      _alphabetMap: [Object],
      _leader: '1'
    },
    arrayify: [Function: arrayify],
    concat: [Function: concat],
    hexConcat: [Function: hexConcat],
    hexDataSlice: [Function: hexDataSlice],
    hexDataLength: [Function: hexDataLength],
    hexlify: [Function: hexlify],
    hexStripZeros: [Function: hexStripZeros],
    hexValue: [Function: hexValue],
    hexZeroPad: [Function: hexZeroPad],
    isBytes: [Function: isBytes],
    isBytesLike: [Function: isBytesLike],
    isHexString: [Function: isHexString],
    joinSignature: [Function: joinSignature],
    zeroPad: [Function: zeroPad],
    splitSignature: [Function: splitSignature],
    stripZeros: [Function: stripZeros],
    _TypedDataEncoder: [Function: TypedDataEncoder] {
      from: [Function (anonymous)],
      getPrimaryType: [Function (anonymous)],
      hashStruct: [Function (anonymous)],
      hashDomain: [Function (anonymous)],
      encode: [Function (anonymous)],
      hash: [Function (anonymous)],
      resolveNames: [Function (anonymous)],
      getPayload: [Function (anonymous)]
    },
    hashMessage: [Function: hashMessage],
    id: [Function: id],
    isValidName: [Function: isValidName],
    namehash: [Function: namehash],
    defaultPath: "m/44'/60'/0'/0/0",
    entropyToMnemonic: [Function: entropyToMnemonic],
    HDNode: [Function: HDNode] {
      _fromSeed: [Function (anonymous)],
      fromMnemonic: [Function (anonymous)],
      fromSeed: [Function (anonymous)],
      fromExtendedKey: [Function (anonymous)]
    },
    isValidMnemonic: [Function: isValidMnemonic],
    mnemonicToEntropy: [Function: mnemonicToEntropy],
    mnemonicToSeed: [Function: mnemonicToSeed],
    getJsonWalletAddress: [Function: getJsonWalletAddress],
    keccak256: [Function: keccak256],
    Logger: [Function: Logger] {
      globalLogger: [Function (anonymous)],
      setCensorship: [Function (anonymous)],
      setLogLevel: [Function (anonymous)],
      from: [Function (anonymous)],
      errors: [Object],
      levels: [Object]
    },
    computeHmac: [Function: computeHmac],
    ripemd160: [Function: ripemd160],
    sha256: [Function: sha256],
    sha512: [Function: sha512],
    solidityKeccak256: [Function: keccak256],
    solidityPack: [Function: pack],
    soliditySha256: [Function: sha256],
    randomBytes: [Function: randomBytes],
    shuffled: [Function: shuffled],
    checkProperties: [Function: checkProperties],
    deepCopy: [Function: deepCopy],
    defineReadOnly: [Function: defineReadOnly],
    getStatic: [Function: getStatic],
    resolveProperties: [Function: resolveProperties],
    shallowCopy: [Function: shallowCopy],
    RLP: { encode: [Function: encode], decode: [Function: decode] },
    computePublicKey: [Function: computePublicKey],
    recoverPublicKey: [Function: recoverPublicKey],
    SigningKey: [Function: SigningKey] { isSigningKey: [Function (anonymous)] },
    formatBytes32String: [Function: formatBytes32String],
    nameprep: [Function: nameprep],
    parseBytes32String: [Function: parseBytes32String],
    _toEscapedUtf8String: [Function: _toEscapedUtf8String],
    toUtf8Bytes: [Function: toUtf8Bytes],
    toUtf8CodePoints: [Function: toUtf8CodePoints],
    toUtf8String: [Function: toUtf8String],
    Utf8ErrorFuncs: {
      error: [Function: errorFunc],
      ignore: [Function: ignoreFunc],
      replace: [Function: replaceFunc]
    },
    computeAddress: [Function: computeAddress],
    parseTransaction: [Function: parse],
    recoverAddress: [Function: recoverAddress],
    serializeTransaction: [Function: serialize],
    commify: [Function: commify],
    formatEther: [Function: formatEther],
    parseEther: [Function: parseEther],
    formatUnits: [Function: formatUnits],
    parseUnits: [Function: parseUnits],
    verifyMessage: [Function: verifyMessage],
    verifyTypedData: [Function: verifyTypedData],
    _fetchData: [Function: _fetchData],
    fetchJson: [Function: fetchJson],
    poll: [Function: poll],
    SupportedAlgorithm: { sha256: 'sha256', sha512: 'sha512' },
    UnicodeNormalizationForm: { current: '', NFC: 'NFC', NFD: 'NFD', NFKC: 'NFKC', NFKD: 'NFKD' },
    Utf8ErrorReason: {
      UNEXPECTED_CONTINUE: 'unexpected continuation byte',
      BAD_PREFIX: 'bad codepoint prefix',
      OVERRUN: 'string overrun',
      MISSING_CONTINUE: 'missing continuation byte',
      OUT_OF_RANGE: 'out of UTF-8 range',
      UTF16_SURROGATE: 'UTF-16 surrogate',
      OVERLONG: 'overlong representation'
    }
  },
  errors: {
    UNKNOWN_ERROR: 'UNKNOWN_ERROR',
    NOT_IMPLEMENTED: 'NOT_IMPLEMENTED',
    UNSUPPORTED_OPERATION: 'UNSUPPORTED_OPERATION',
    NETWORK_ERROR: 'NETWORK_ERROR',
    SERVER_ERROR: 'SERVER_ERROR',
    TIMEOUT: 'TIMEOUT',
    BUFFER_OVERRUN: 'BUFFER_OVERRUN',
    NUMERIC_FAULT: 'NUMERIC_FAULT',
    MISSING_NEW: 'MISSING_NEW',
    INVALID_ARGUMENT: 'INVALID_ARGUMENT',
    MISSING_ARGUMENT: 'MISSING_ARGUMENT',
    UNEXPECTED_ARGUMENT: 'UNEXPECTED_ARGUMENT',
    CALL_EXCEPTION: 'CALL_EXCEPTION',
    INSUFFICIENT_FUNDS: 'INSUFFICIENT_FUNDS',
    NONCE_EXPIRED: 'NONCE_EXPIRED',
    REPLACEMENT_UNDERPRICED: 'REPLACEMENT_UNDERPRICED',
    UNPREDICTABLE_GAS_LIMIT: 'UNPREDICTABLE_GAS_LIMIT'
  },
  version: 'ethers/5.0.31',
  logger: Logger { version: 'ethers/5.0.31' },
  provider: EthersProviderWrapper {
    _isProvider: true,
    _events: [],
    _emitted: { block: -2 },
    formatter: Formatter { formats: [Object] },
    anyNetwork: false,
    _networkPromise: Promise { <pending> },
    _maxInternalBlockNumber: -1024,
    _lastBlockNumber: -2,
    _pollingInterval: 4000,
    _fastQueryDate: 0,
    connection: { url: 'http://localhost:8545' },
    _nextId: 42,
    _hardhatProvider: BackwardsCompatibilityProviderAdapter {
      _wrapped: FixedGasPriceProvider {
        _wrapped: FixedGasProvider {
          _wrapped: [AutomaticSenderProvider],
          _wrappedProvider: [AutomaticSenderProvider],
          _gasLimit: 9500000
        },
        _wrappedProvider: FixedGasProvider {
          _wrapped: [AutomaticSenderProvider],
          _wrappedProvider: [AutomaticSenderProvider],
          _gasLimit: 9500000
        },
        _gasPrice: 8000000000
      },
      _provider: FixedGasPriceProvider {
        _wrapped: FixedGasProvider {
          _wrapped: [AutomaticSenderProvider],
          _wrappedProvider: [AutomaticSenderProvider],
          _gasLimit: 9500000
        },
        _wrappedProvider: FixedGasProvider {
          _wrapped: [AutomaticSenderProvider],
          _wrappedProvider: [AutomaticSenderProvider],
          _gasLimit: 9500000
        },
        _gasPrice: 8000000000
      },
      sendAsync: [Function: bound sendAsync],
      send: [Function: bound send],
      _sendJsonRpcRequest: [Function: bound _sendJsonRpcRequest] AsyncFunction
    }
  },
  getSigners: [AsyncFunction: getSigners],
  getContractFactory: [Function: bound getContractFactory] AsyncFunction,
  getContractAt: [Function: bound getContractAt] AsyncFunction
}
> const V1 = await ethers.getContr
undefined
> const V1 = await ethers.getContr
undefined
> const V1 = await ethers.getContractFactory("V1");
undefined
> const WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
undefined
> const MFI_ADDRESS = "0xAa4e3edb11AFa93c41db59842b29de64b72E355B";
undefined
> const REAL_TREASURY = "0x16F3Fc1E4BA9d70f47387b902fa5d21020b5C6B5";
undefined
> const UNISWAP_FACTORY = "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f";
undefined
> const SUSHISWAP_FACTORY = "0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac";
undefined
> const USDC_ADDRESS = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
undefined
> V1.deploy(treasury,
...                     WETH,
...                     feesPer10k,
...                     MFI_ADDRESS,
...                     UNISWAP_FACTORY,
...                     SUSHISWAP_FACTORY,
...                     USDC_ADDRESS);
Uncaught ReferenceError: treasury is not defined
> let treasury = REAL_TREASURY;
undefined
>     let feesPer10k = 10;
undefined
> V1.deploy(treasury,WETH,
...                     feesPer10k,
...                     MFI_ADDRESS,
...                     UNISWAP_FACTORY,
...                     SUSHISWAP_FACTORY,
...                     USDC_ADDRESS);
Promise { <pending> }
> (node:3395) UnhandledPromiseRejectionWarning: Error: Transaction reverted: contract call run out of gas and made the transaction revert
    at <UnrecognizedContract>.<unknown> (unknown)
    at V1.constructor (contracts/V1.sol:55)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at EthModule._estimateGasAction (/home/tixelbook/projects/marginswap-core/node_modules/hardhat/src/internal/hardhat-network/provider/modules/eth.ts:402:9)
    at HardhatNetworkProvider.request (/home/tixelbook/projects/marginswap-core/node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:102:18)
    at EthersProviderWrapper.send (/home/tixelbook/projects/marginswap-core/node_modules/@nomiclabs/hardhat-ethers/src/ethers-provider-wrapper.ts:13:20)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:3395) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 16)
(node:3395) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

> const Fund = ethers.getContractFactory("Fund");
undefined
> const Roles = ethers.getContractFactory("Roles");
undefined
> const Fund = await ethers.getContractFactory("Fund");
Uncaught TypeError: Assignment to constant variable.
> const Fund1 = await ethers.getContractFactory("Fund");
undefined
> const Roles1 = await ethers.getContractFactory("Roles");
undefined
> const roles = Roles.deploy();
Uncaught TypeError: Roles.deploy is not a function
> const roles = Roles1.deploy();
Uncaught SyntaxError: Identifier 'roles' has already been declared
> const roles1 = Roles1.deploy();
undefined
> roles2 = await roles1;
Contract {
  interface: Interface {
    fragments: [
      [EventFragment],
      [FunctionFragment],
      [FunctionFragment],
      [FunctionFragment],
      [FunctionFragment],
      [FunctionFragment],
      [FunctionFragment],
      [FunctionFragment],
      [FunctionFragment],
      [FunctionFragment]
    ],
    _abiCoder: AbiCoder { coerceFunc: null },
    functions: {
      'getRole(address,uint8)': [FunctionFragment],
      'giveRole(uint8,address)': [FunctionFragment],
      'mainCharacters(uint8)': [FunctionFragment],
      'owner()': [FunctionFragment],
      'removeRole(uint8,address)': [FunctionFragment],
      'renounceOwnership()': [FunctionFragment],
      'roles(address,uint8)': [FunctionFragment],
      'setMainCharacter(uint8,address)': [FunctionFragment],
      'transferOwnership(address)': [FunctionFragment]
    },
    errors: {},
    events: { 'OwnershipTransferred(address,address)': [EventFragment] },
    structs: {},
    deploy: ConstructorFragment {
      name: null,
      type: 'constructor',
      inputs: [],
      payable: false,
      stateMutability: 'nonpayable',
      gas: null,
      _isFragment: true
    },
    _isInterface: true
  },
  provider: EthersProviderWrapper {
    _isProvider: true,
    _events: [],
    _emitted: { block: -2 },
    formatter: Formatter { formats: [Object] },
    anyNetwork: false,
    _networkPromise: Promise { [Object] },
    _maxInternalBlockNumber: 1,
    _lastBlockNumber: -2,
    _pollingInterval: 4000,
    _fastQueryDate: 1613898802149,
    connection: { url: 'http://localhost:8545' },
    _nextId: 42,
    _hardhatProvider: BackwardsCompatibilityProviderAdapter {
      _wrapped: FixedGasPriceProvider {
        _wrapped: FixedGasProvider {
          _wrapped: [AutomaticSenderProvider],
          _wrappedProvider: [AutomaticSenderProvider],
          _gasLimit: 9500000
        },
        _wrappedProvider: FixedGasProvider {
          _wrapped: [AutomaticSenderProvider],
          _wrappedProvider: [AutomaticSenderProvider],
          _gasLimit: 9500000
        },
        _gasPrice: 8000000000
      },
      _provider: FixedGasPriceProvider {
        _wrapped: FixedGasProvider {
          _wrapped: [AutomaticSenderProvider],
          _wrappedProvider: [AutomaticSenderProvider],
          _gasLimit: 9500000
        },
        _wrappedProvider: FixedGasProvider {
          _wrapped: [AutomaticSenderProvider],
          _wrappedProvider: [AutomaticSenderProvider],
          _gasLimit: 9500000
        },
        _gasPrice: 8000000000
      },
      sendAsync: [Function: bound sendAsync],
      send: [Function: bound send],
      _sendJsonRpcRequest: [Function: bound _sendJsonRpcRequest] AsyncFunction
    },
    _network: { chainId: 31337, name: 'unknown' },
    _internalBlockNumber: Promise { [Object] },
    _fastBlockNumber: 1,
    _fastBlockNumberPromise: Promise { 1 }
  },
  signer: SignerWithAddress {
    _isSigner: true,
    address: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
    _signer: JsonRpcSigner {
      _isSigner: true,
      provider: [EthersProviderWrapper],
      _address: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
      _index: null
    },
    provider: EthersProviderWrapper {
      _isProvider: true,
      _events: [],
      _emitted: [Object],
      formatter: [Formatter],
      anyNetwork: false,
      _networkPromise: [Promise],
      _maxInternalBlockNumber: 1,
      _lastBlockNumber: -2,
      _pollingInterval: 4000,
      _fastQueryDate: 1613898802149,
      connection: [Object],
      _nextId: 42,
      _hardhatProvider: BackwardsCompatibilityProviderAdapter {
        _wrapped: FixedGasPriceProvider {
          _wrapped: FixedGasProvider {
            _wrapped: [AutomaticSenderProvider],
            _wrappedProvider: [AutomaticSenderProvider],
            _gasLimit: 9500000
          },
          _wrappedProvider: FixedGasProvider {
            _wrapped: [AutomaticSenderProvider],
            _wrappedProvider: [AutomaticSenderProvider],
            _gasLimit: 9500000
          },
          _gasPrice: 8000000000
        },
        _provider: FixedGasPriceProvider {
          _wrapped: FixedGasProvider {
            _wrapped: [AutomaticSenderProvider],
            _wrappedProvider: [AutomaticSenderProvider],
            _gasLimit: 9500000
          },
          _wrappedProvider: FixedGasProvider {
            _wrapped: [AutomaticSenderProvider],
            _wrappedProvider: [AutomaticSenderProvider],
            _gasLimit: 9500000
          },
          _gasPrice: 8000000000
        },
        sendAsync: [Function: bound sendAsync],
        send: [Function: bound send],
        _sendJsonRpcRequest: [Function: bound _sendJsonRpcRequest] AsyncFunction
      },
      _network: [Object],
      _internalBlockNumber: [Promise],
      _fastBlockNumber: 1,
      _fastBlockNumberPromise: [Promise]
    }
  },
  callStatic: {
    'getRole(address,uint8)': [Function (anonymous)],
    'giveRole(uint8,address)': [Function (anonymous)],
    'mainCharacters(uint8)': [Function (anonymous)],
    'owner()': [Function (anonymous)],
    'removeRole(uint8,address)': [Function (anonymous)],
    'renounceOwnership()': [Function (anonymous)],
    'roles(address,uint8)': [Function (anonymous)],
    'setMainCharacter(uint8,address)': [Function (anonymous)],
    'transferOwnership(address)': [Function (anonymous)],
    getRole: [Function (anonymous)],
    giveRole: [Function (anonymous)],
    mainCharacters: [Function (anonymous)],
    owner: [Function (anonymous)],
    removeRole: [Function (anonymous)],
    renounceOwnership: [Function (anonymous)],
    roles: [Function (anonymous)],
    setMainCharacter: [Function (anonymous)],
    transferOwnership: [Function (anonymous)]
  },
  estimateGas: {
    'getRole(address,uint8)': [Function (anonymous)],
    'giveRole(uint8,address)': [Function (anonymous)],
    'mainCharacters(uint8)': [Function (anonymous)],
    'owner()': [Function (anonymous)],
    'removeRole(uint8,address)': [Function (anonymous)],
    'renounceOwnership()': [Function (anonymous)],
    'roles(address,uint8)': [Function (anonymous)],
    'setMainCharacter(uint8,address)': [Function (anonymous)],
    'transferOwnership(address)': [Function (anonymous)],
    getRole: [Function (anonymous)],
    giveRole: [Function (anonymous)],
    mainCharacters: [Function (anonymous)],
    owner: [Function (anonymous)],
    removeRole: [Function (anonymous)],
    renounceOwnership: [Function (anonymous)],
    roles: [Function (anonymous)],
    setMainCharacter: [Function (anonymous)],
    transferOwnership: [Function (anonymous)]
  },
  functions: {
    'getRole(address,uint8)': [Function (anonymous)],
    'giveRole(uint8,address)': [Function (anonymous)],
    'mainCharacters(uint8)': [Function (anonymous)],
    'owner()': [Function (anonymous)],
    'removeRole(uint8,address)': [Function (anonymous)],
    'renounceOwnership()': [Function (anonymous)],
    'roles(address,uint8)': [Function (anonymous)],
    'setMainCharacter(uint8,address)': [Function (anonymous)],
    'transferOwnership(address)': [Function (anonymous)],
    getRole: [Function (anonymous)],
    giveRole: [Function (anonymous)],
    mainCharacters: [Function (anonymous)],
    owner: [Function (anonymous)],
    removeRole: [Function (anonymous)],
    renounceOwnership: [Function (anonymous)],
    roles: [Function (anonymous)],
    setMainCharacter: [Function (anonymous)],
    transferOwnership: [Function (anonymous)]
  },
  populateTransaction: {
    'getRole(address,uint8)': [Function (anonymous)],
    'giveRole(uint8,address)': [Function (anonymous)],
    'mainCharacters(uint8)': [Function (anonymous)],
    'owner()': [Function (anonymous)],
    'removeRole(uint8,address)': [Function (anonymous)],
    'renounceOwnership()': [Function (anonymous)],
    'roles(address,uint8)': [Function (anonymous)],
    'setMainCharacter(uint8,address)': [Function (anonymous)],
    'transferOwnership(address)': [Function (anonymous)],
    getRole: [Function (anonymous)],
    giveRole: [Function (anonymous)],
    mainCharacters: [Function (anonymous)],
    owner: [Function (anonymous)],
    removeRole: [Function (anonymous)],
    renounceOwnership: [Function (anonymous)],
    roles: [Function (anonymous)],
    setMainCharacter: [Function (anonymous)],
    transferOwnership: [Function (anonymous)]
  },
  filters: {
    'OwnershipTransferred(address,address)': [Function (anonymous)],
    OwnershipTransferred: [Function (anonymous)]
  },
  _runningEvents: {},
  _wrappedEmits: {},
  address: '0x5FbDB2315678afecb367f032d93F642f64180aa3',
  resolvedAddress: Promise { '0x5FbDB2315678afecb367f032d93F642f64180aa3' },
  'getRole(address,uint8)': [Function (anonymous)],
  'giveRole(uint8,address)': [Function (anonymous)],
  'mainCharacters(uint8)': [Function (anonymous)],
  'owner()': [Function (anonymous)],
  'removeRole(uint8,address)': [Function (anonymous)],
  'renounceOwnership()': [Function (anonymous)],
  'roles(address,uint8)': [Function (anonymous)],
  'setMainCharacter(uint8,address)': [Function (anonymous)],
  'transferOwnership(address)': [Function (anonymous)],
  getRole: [Function (anonymous)],
  giveRole: [Function (anonymous)],
  mainCharacters: [Function (anonymous)],
  owner: [Function (anonymous)],
  removeRole: [Function (anonymous)],
  renounceOwnership: [Function (anonymous)],
  roles: [Function (anonymous)],
  setMainCharacter: [Function (anonymous)],
  transferOwnership: [Function (anonymous)],
  deployTransaction: {
    hash: '0x277ff13402c2de03c61493b9289671afb8c2fd69eb0b1f0e1b1b86b32a321f2d',
    blockHash: '0xc1993c987cd2fa35ebd0c216ea39b717a2212d976c601ab205ae9fea4b55ea51',
    blockNumber: 1,
    transactionIndex: 0,
    confirmations: 1,
    from: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
    gasPrice: BigNumber { _hex: '0x01dcd65000', _isBigNumber: true },
    gasLimit: BigNumber { _hex: '0x0b4810', _isBigNumber: true },
    to: null,
    value: BigNumber { _hex: '0x00', _isBigNumber: true },
    nonce: 0,
    data: '0x608060405234801561001057600080fd5b5060006100216100c460201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3506100cc565b600033905090565b610bfd806100db6000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c8063715018a611610066578063715018a6146101fc5780638a1713c6146102065780638da5cb5b14610257578063a716b97f1461028b578063f2fde38b146102f257610093565b80630b886c191461009857806336214c78146100ff5780633f1609ef1461015a57806346cd9bd1146101ab575b600080fd5b6100e7600480360360408110156100ae57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff169060200190929190505050610336565b60405180821515815260200191505060405180910390f35b61012e6004803603602081101561011557600080fd5b81019080803560ff169060200190929190505050610365565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101a96004803603604081101561017057600080fd5b81019080803560ff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610398565b005b6101fa600480360360408110156101c157600080fd5b81019080803560ff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104cc565b005b610204610616565b005b6102556004803603604081101561021c57600080fd5b81019080803560ff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061079c565b005b61025f6108e7565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6102da600480360360408110156102a157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff169060200190929190505050610910565b60405180821515815260200191505060405180910390f35b6103346004803603602081101561030857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061098e565b005b60016020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60026020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6103a0610b99565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610460576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b806002600084600581111561047157fe5b600581111561047c57fe5b815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6104d4610b99565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610594576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60018060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008460058111156105e257fe5b60058111156105ed57fe5b815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b61061e610b99565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146106de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6107a4610b99565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610864576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008460058111156108b357fe5b60058111156108be57fe5b815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083600581111561095f57fe5b600581111561096a57fe5b815260200190815260200160002060009054906101000a900460ff16905092915050565b610996610b99565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610a56576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610adc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180610ba26026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60003390509056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373a2646970667358221220adaca3a29ddb3c591a4eb32fd4da153a31008bd21eba904f2d68eb7ce8fa7c5264736f6c63430007030033',
    r: '0x884dd4c8e8e235c6e032b6c03f2baffa375df382d9a1b7f2d740e9e69762b492',
    s: '0x74e173031839072a3fb41269d9fb23da0c2608ef7c3c9d7bfcf89c3b18b41b9e',
    v: 62710,
    creates: '0x5FbDB2315678afecb367f032d93F642f64180aa3',
    chainId: 31337,
    wait: [Function (anonymous)]
  }
}
> const fund = await Fund1.deploy(WETH, roles2.address);
undefined
> fund.transferOwnership(targetOwner);
Uncaught ReferenceError: targetOwner is not defined
> fund.transferOwnership(treasury);
Promise { <pending> }
> const Admin = await ethers.getContractFactory("Admin");
undefined
> const admin = Admin.deploy(feesPer10k, MFI_ADDRESS, roles2.address);
undefined
> admin1 = await admin;
Contract {
  interface: Interface {
    fragments: [
      [ConstructorFragment], [EventFragment],
      [FunctionFragment],    [FunctionFragment],
      [FunctionFragment],    [FunctionFragment],
      [FunctionFragment],    [FunctionFragment],
      [FunctionFragment],    [FunctionFragment],
      [FunctionFragment],    [FunctionFragment],
      [FunctionFragment],    [FunctionFragment],
      [FunctionFragment],    [FunctionFragment],
      [FunctionFragment],    [FunctionFragment],
      [FunctionFragment]
    ],
    _abiCoder: AbiCoder { coerceFunc: null },
    functions: {
      'addDelegate(address,address)': [FunctionFragment],
      'addTradingFees(address,uint256)': [FunctionFragment],
      'callMargin(address[])': [FunctionFragment],
      'collectedFees(address)': [FunctionFragment],
      'marginCallerStake(uint256)': [FunctionFragment],
      'mcDelegatedTo(address,address)': [FunctionFragment],
      'mcStakes(address)': [FunctionFragment],
      'owner()': [FunctionFragment],
      'removeDelegate(address,address)': [FunctionFragment],
      'renounceOwnership()': [FunctionFragment],
      'roles()': [FunctionFragment],
      'stake(uint256)': [FunctionFragment],
      'stakes(address)': [FunctionFragment],
      'subtractTradingFees(address,uint256)': [FunctionFragment],
      'totalStakes()': [FunctionFragment],
      'transferOwnership(address)': [FunctionFragment],
      'unstake(uint256,address)': [FunctionFragment]
    },
    errors: {},
    events: { 'OwnershipTransferred(address,address)': [EventFragment] },
    structs: {},
    deploy: ConstructorFragment {
      name: null,
      type: 'constructor',
      inputs: [Array],
      payable: false,
      stateMutability: 'nonpayable',
      gas: null,
      _isFragment: true
    },
    _isInterface: true
  },
  provider: EthersProviderWrapper {
    _isProvider: true,
    _events: [],
    _emitted: {
      block: -2,
      't:0x7c6d0242a37a89307f47449b8ba8e074b337dccc82d8f35f8ca1b60a41f3d36f': 2
    },
    formatter: Formatter { formats: [Object] },
    anyNetwork: false,
    _networkPromise: Promise { [Object] },
    _maxInternalBlockNumber: 4,
    _lastBlockNumber: -2,
    _pollingInterval: 4000,
    _fastQueryDate: 1613899179964,
    connection: { url: 'http://localhost:8545' },
    _nextId: 42,
    _hardhatProvider: BackwardsCompatibilityProviderAdapter {
      _wrapped: FixedGasPriceProvider {
        _wrapped: FixedGasProvider {
          _wrapped: [AutomaticSenderProvider],
          _wrappedProvider: [AutomaticSenderProvider],
          _gasLimit: 9500000
        },
        _wrappedProvider: FixedGasProvider {
          _wrapped: [AutomaticSenderProvider],
          _wrappedProvider: [AutomaticSenderProvider],
          _gasLimit: 9500000
        },
        _gasPrice: 8000000000
      },
      _provider: FixedGasPriceProvider {
        _wrapped: FixedGasProvider {
          _wrapped: [AutomaticSenderProvider],
          _wrappedProvider: [AutomaticSenderProvider],
          _gasLimit: 9500000
        },
        _wrappedProvider: FixedGasProvider {
          _wrapped: [AutomaticSenderProvider],
          _wrappedProvider: [AutomaticSenderProvider],
          _gasLimit: 9500000
        },
        _gasPrice: 8000000000
      },
      sendAsync: [Function: bound sendAsync],
      send: [Function: bound send],
      _sendJsonRpcRequest: [Function: bound _sendJsonRpcRequest] AsyncFunction
    },
    _network: { chainId: 31337, name: 'unknown' },
    _internalBlockNumber: Promise { [Object] },
    _fastBlockNumber: 4,
    _fastBlockNumberPromise: Promise { 4 }
  },
  signer: SignerWithAddress {
    _isSigner: true,
    address: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
    _signer: JsonRpcSigner {
      _isSigner: true,
      provider: [EthersProviderWrapper],
      _address: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
      _index: null
    },
    provider: EthersProviderWrapper {
      _isProvider: true,
      _events: [],
      _emitted: [Object],
      formatter: [Formatter],
      anyNetwork: false,
      _networkPromise: [Promise],
      _maxInternalBlockNumber: 4,
      _lastBlockNumber: -2,
      _pollingInterval: 4000,
      _fastQueryDate: 1613899179964,
      connection: [Object],
      _nextId: 42,
      _hardhatProvider: BackwardsCompatibilityProviderAdapter {
        _wrapped: FixedGasPriceProvider {
          _wrapped: FixedGasProvider {
            _wrapped: [AutomaticSenderProvider],
            _wrappedProvider: [AutomaticSenderProvider],
            _gasLimit: 9500000
          },
          _wrappedProvider: FixedGasProvider {
            _wrapped: [AutomaticSenderProvider],
            _wrappedProvider: [AutomaticSenderProvider],
            _gasLimit: 9500000
          },
          _gasPrice: 8000000000
        },
        _provider: FixedGasPriceProvider {
          _wrapped: FixedGasProvider {
            _wrapped: [AutomaticSenderProvider],
            _wrappedProvider: [AutomaticSenderProvider],
            _gasLimit: 9500000
          },
          _wrappedProvider: FixedGasProvider {
            _wrapped: [AutomaticSenderProvider],
            _wrappedProvider: [AutomaticSenderProvider],
            _gasLimit: 9500000
          },
          _gasPrice: 8000000000
        },
        sendAsync: [Function: bound sendAsync],
        send: [Function: bound send],
        _sendJsonRpcRequest: [Function: bound _sendJsonRpcRequest] AsyncFunction
      },
      _network: [Object],
      _internalBlockNumber: [Promise],
      _fastBlockNumber: 4,
      _fastBlockNumberPromise: [Promise]
    }
  },
  callStatic: {
    'addDelegate(address,address)': [Function (anonymous)],
    'addTradingFees(address,uint256)': [Function (anonymous)],
    'callMargin(address[])': [Function (anonymous)],
    'collectedFees(address)': [Function (anonymous)],
    'marginCallerStake(uint256)': [Function (anonymous)],
    'mcDelegatedTo(address,address)': [Function (anonymous)],
    'mcStakes(address)': [Function (anonymous)],
    'owner()': [Function (anonymous)],
    'removeDelegate(address,address)': [Function (anonymous)],
    'renounceOwnership()': [Function (anonymous)],
    'roles()': [Function (anonymous)],
    'stake(uint256)': [Function (anonymous)],
    'stakes(address)': [Function (anonymous)],
    'subtractTradingFees(address,uint256)': [Function (anonymous)],
    'totalStakes()': [Function (anonymous)],
    'transferOwnership(address)': [Function (anonymous)],
    'unstake(uint256,address)': [Function (anonymous)],
    addDelegate: [Function (anonymous)],
    addTradingFees: [Function (anonymous)],
    callMargin: [Function (anonymous)],
    collectedFees: [Function (anonymous)],
    marginCallerStake: [Function (anonymous)],
    mcDelegatedTo: [Function (anonymous)],
    mcStakes: [Function (anonymous)],
    owner: [Function (anonymous)],
    removeDelegate: [Function (anonymous)],
    renounceOwnership: [Function (anonymous)],
    roles: [Function (anonymous)],
    stake: [Function (anonymous)],
    stakes: [Function (anonymous)],
    subtractTradingFees: [Function (anonymous)],
    totalStakes: [Function (anonymous)],
    transferOwnership: [Function (anonymous)],
    unstake: [Function (anonymous)]
  },
  estimateGas: {
    'addDelegate(address,address)': [Function (anonymous)],
    'addTradingFees(address,uint256)': [Function (anonymous)],
    'callMargin(address[])': [Function (anonymous)],
    'collectedFees(address)': [Function (anonymous)],
    'marginCallerStake(uint256)': [Function (anonymous)],
    'mcDelegatedTo(address,address)': [Function (anonymous)],
    'mcStakes(address)': [Function (anonymous)],
    'owner()': [Function (anonymous)],
    'removeDelegate(address,address)': [Function (anonymous)],
    'renounceOwnership()': [Function (anonymous)],
    'roles()': [Function (anonymous)],
    'stake(uint256)': [Function (anonymous)],
    'stakes(address)': [Function (anonymous)],
    'subtractTradingFees(address,uint256)': [Function (anonymous)],
    'totalStakes()': [Function (anonymous)],
    'transferOwnership(address)': [Function (anonymous)],
    'unstake(uint256,address)': [Function (anonymous)],
    addDelegate: [Function (anonymous)],
    addTradingFees: [Function (anonymous)],
    callMargin: [Function (anonymous)],
    collectedFees: [Function (anonymous)],
    marginCallerStake: [Function (anonymous)],
    mcDelegatedTo: [Function (anonymous)],
    mcStakes: [Function (anonymous)],
    owner: [Function (anonymous)],
    removeDelegate: [Function (anonymous)],
    renounceOwnership: [Function (anonymous)],
    roles: [Function (anonymous)],
    stake: [Function (anonymous)],
    stakes: [Function (anonymous)],
    subtractTradingFees: [Function (anonymous)],
    totalStakes: [Function (anonymous)],
    transferOwnership: [Function (anonymous)],
    unstake: [Function (anonymous)]
  },
  functions: {
    'addDelegate(address,address)': [Function (anonymous)],
    'addTradingFees(address,uint256)': [Function (anonymous)],
    'callMargin(address[])': [Function (anonymous)],
    'collectedFees(address)': [Function (anonymous)],
    'marginCallerStake(uint256)': [Function (anonymous)],
    'mcDelegatedTo(address,address)': [Function (anonymous)],
    'mcStakes(address)': [Function (anonymous)],
    'owner()': [Function (anonymous)],
    'removeDelegate(address,address)': [Function (anonymous)],
    'renounceOwnership()': [Function (anonymous)],
    'roles()': [Function (anonymous)],
    'stake(uint256)': [Function (anonymous)],
    'stakes(address)': [Function (anonymous)],
    'subtractTradingFees(address,uint256)': [Function (anonymous)],
    'totalStakes()': [Function (anonymous)],
    'transferOwnership(address)': [Function (anonymous)],
    'unstake(uint256,address)': [Function (anonymous)],
    addDelegate: [Function (anonymous)],
    addTradingFees: [Function (anonymous)],
    callMargin: [Function (anonymous)],
    collectedFees: [Function (anonymous)],
    marginCallerStake: [Function (anonymous)],
    mcDelegatedTo: [Function (anonymous)],
    mcStakes: [Function (anonymous)],
    owner: [Function (anonymous)],
    removeDelegate: [Function (anonymous)],
    renounceOwnership: [Function (anonymous)],
    roles: [Function (anonymous)],
    stake: [Function (anonymous)],
    stakes: [Function (anonymous)],
    subtractTradingFees: [Function (anonymous)],
    totalStakes: [Function (anonymous)],
    transferOwnership: [Function (anonymous)],
    unstake: [Function (anonymous)]
  },
  populateTransaction: {
    'addDelegate(address,address)': [Function (anonymous)],
    'addTradingFees(address,uint256)': [Function (anonymous)],
    'callMargin(address[])': [Function (anonymous)],
    'collectedFees(address)': [Function (anonymous)],
    'marginCallerStake(uint256)': [Function (anonymous)],
    'mcDelegatedTo(address,address)': [Function (anonymous)],
    'mcStakes(address)': [Function (anonymous)],
    'owner()': [Function (anonymous)],
    'removeDelegate(address,address)': [Function (anonymous)],
    'renounceOwnership()': [Function (anonymous)],
    'roles()': [Function (anonymous)],
    'stake(uint256)': [Function (anonymous)],
    'stakes(address)': [Function (anonymous)],
    'subtractTradingFees(address,uint256)': [Function (anonymous)],
    'totalStakes()': [Function (anonymous)],
    'transferOwnership(address)': [Function (anonymous)],
    'unstake(uint256,address)': [Function (anonymous)],
    addDelegate: [Function (anonymous)],
    addTradingFees: [Function (anonymous)],
    callMargin: [Function (anonymous)],
    collectedFees: [Function (anonymous)],
    marginCallerStake: [Function (anonymous)],
    mcDelegatedTo: [Function (anonymous)],
    mcStakes: [Function (anonymous)],
    owner: [Function (anonymous)],
    removeDelegate: [Function (anonymous)],
    renounceOwnership: [Function (anonymous)],
    roles: [Function (anonymous)],
    stake: [Function (anonymous)],
    stakes: [Function (anonymous)],
    subtractTradingFees: [Function (anonymous)],
    totalStakes: [Function (anonymous)],
    transferOwnership: [Function (anonymous)],
    unstake: [Function (anonymous)]
  },
  filters: {
    'OwnershipTransferred(address,address)': [Function (anonymous)],
    OwnershipTransferred: [Function (anonymous)]
  },
  _runningEvents: {},
  _wrappedEmits: {},
  address: '0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9',
  resolvedAddress: Promise { '0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9' },
  'addDelegate(address,address)': [Function (anonymous)],
  'addTradingFees(address,uint256)': [Function (anonymous)],
  'callMargin(address[])': [Function (anonymous)],
  'collectedFees(address)': [Function (anonymous)],
  'marginCallerStake(uint256)': [Function (anonymous)],
  'mcDelegatedTo(address,address)': [Function (anonymous)],
  'mcStakes(address)': [Function (anonymous)],
  'owner()': [Function (anonymous)],
  'removeDelegate(address,address)': [Function (anonymous)],
  'renounceOwnership()': [Function (anonymous)],
  'roles()': [Function (anonymous)],
  'stake(uint256)': [Function (anonymous)],
  'stakes(address)': [Function (anonymous)],
  'subtractTradingFees(address,uint256)': [Function (anonymous)],
  'totalStakes()': [Function (anonymous)],
  'transferOwnership(address)': [Function (anonymous)],
  'unstake(uint256,address)': [Function (anonymous)],
  addDelegate: [Function (anonymous)],
  addTradingFees: [Function (anonymous)],
  callMargin: [Function (anonymous)],
  collectedFees: [Function (anonymous)],
  marginCallerStake: [Function (anonymous)],
  mcDelegatedTo: [Function (anonymous)],
  mcStakes: [Function (anonymous)],
  owner: [Function (anonymous)],
  removeDelegate: [Function (anonymous)],
  renounceOwnership: [Function (anonymous)],
  roles: [Function (anonymous)],
  stake: [Function (anonymous)],
  stakes: [Function (anonymous)],
  subtractTradingFees: [Function (anonymous)],
  totalStakes: [Function (anonymous)],
  transferOwnership: [Function (anonymous)],
  unstake: [Function (anonymous)],
  deployTransaction: {
    hash: '0xb3bf948f6546e37564014f02b8daa5e9395ad0cf227140b6bd19a25830b4f189',
    blockHash: '0x8e54dec11997bbe4d4aafbda0c949aa499a7a0037afd3b214be6d6c89a4210a6',
    blockNumber: 4,
    transactionIndex: 0,
    confirmations: 1,
    from: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
    gasPrice: BigNumber { _hex: '0x01dcd65000', _isBigNumber: true },
    gasLimit: BigNumber { _hex: '0x1c3821', _isBigNumber: true },
    to: null,
    value: BigNumber { _hex: '0x00', _isBigNumber: true },
    nonce: 3,
    data: '0x608060405234801561001057600080fd5b5060405161204a38038061204a8339818101604052606081101561003357600080fd5b8101908080519060200190929190805190602001909291908051906020019092919050505080806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505060006100aa6101a860201b60201c565b905080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35081600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600581905550670de0b6b3a76400006007819055505050506101b0565b600033905090565b611e8b806101bf6000396000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c8063715018a6116100a2578063a694fc3a11610071578063a694fc3a146104c5578063bf9befb1146104f3578063e909ebfa14610511578063ed95eda014610575578063f2fde38b1461062d5761010b565b8063715018a6146103bf57806381fe8039146103c95780638381e182146104435780638da5cb5b146104915761010b565b8063392f5f64116100de578063392f5f64146102525780633f0e9edf1461028657806356fc9124146102e857806367cbf42d1461035d5761010b565b8063020d308d1461011057806316934fc4146101745780631cead9a7146101cc5780632c00d4a714610224575b600080fd5b6101726004803603604081101561012657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610671565b005b6101b66004803603602081101561018a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061081f565b6040518082815260200191505060405180910390f35b61020e600480360360208110156101e257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610837565b6040518082815260200191505060405180910390f35b6102506004803603602081101561023a57600080fd5b810190808035906020019092919050505061084f565b005b61025a610ab9565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6102d26004803603604081101561029c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610add565b6040518082815260200191505060405180910390f35b61032a600480360360208110156102fe57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bc3565b604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390f35b6103a96004803603604081101561037357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610c07565b6040518082815260200191505060405180910390f35b6103c7610ce9565b005b61042b600480360360408110156103df57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610e74565b60405180821515815260200191505060405180910390f35b61048f6004803603604081101561045957600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ea3565b005b61049961104c565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6104f1600480360360208110156104db57600080fd5b8101908080359060200190929190505050611076565b005b6104fb611083565b6040518082815260200191505060405180910390f35b6105736004803603604081101561052757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611089565b005b61062b6004803603602081101561058b57600080fd5b81019080803590602001906401000000008111156105a857600080fd5b8201836020820111156105ba57600080fd5b803590602001918460208302840111640100000000831117156105dc57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050509192919290505050611237565b005b61066f6004803603602081101561064357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506114b8565b005b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806107315750600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610786576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180611dad6030913960400191505060405180910390fd5b6000600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b60036020528060005260406000206000915090505481565b60066020528060005260406000206000915090505481565b600754600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154820110156108ee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180611d846029913960400191505060405180910390fd5b6108f833826116c8565b6000600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001541415610ab65780600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000181905550610992611871565b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503360086000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000610ae833611abb565b610b5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4e6f7420617574686f72697a656420746f20736f75726365206665657300000081525060200191505060405180910390fd5b60055461271001826005540281610b6d57fe5b04905080600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555092915050565b60086020528060005260406000206000915090508060000154908060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905082565b6000610c1233611abb565b610c84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4e6f7420617574686f72697a656420746f20736f75726365206665657300000081525060200191505060405180910390fd5b612710826005540281610c9357fe5b04905080600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555092915050565b610cf1611b9b565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610db3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60096020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b81600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600460008282540392505081905550610f08611ba3565b73ffffffffffffffffffffffffffffffffffffffff1663d9caed12600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683856040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b158015610fb857600080fd5b505af1158015610fcc573d6000803e3d6000fd5b505050506040513d6020811015610fe257600080fd5b8101908080519060200190929190505050611048576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526032815260200180611e246032913960400191505060405180910390fd5b5050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b61108033826116c8565b50565b60045481565b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806111495750600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b61119e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180611dad6030913960400191505060405180910390fd5b6001600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146112bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603a815260200180611d24603a913960400191505060405180910390fd5b60006112c5611871565b905060003373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806113895750600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b90506000611395611c63565b73ffffffffffffffffffffffffffffffffffffffff166315dc6a28856113b9611871565b33866040518563ffffffff1660e01b815260040180806020018573ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018315158152602001828103825286818151815260200191508051906020019060200280838360005b8381101561144d578082015181840152602081019050611432565b5050505090500195505050505050602060405180830381600087803b15801561147557600080fd5b505af1158015611489573d6000803e3d6000fd5b505050506040513d602081101561149f57600080fd5b8101908080519060200190929190505050905050505050565b6114c0611b9b565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611582576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611608576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180611d5e6026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6116d0611ba3565b73ffffffffffffffffffffffffffffffffffffffff1663b3db428b83600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b15801561178057600080fd5b505af1158015611794573d6000803e3d6000fd5b505050506040513d60208110156117aa57600080fd5b8101908080519060200190929190505050611810576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526047815260200180611ddd6047913960600191505060405180910390fd5b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550806004600082825401925050819055505050565b60005b60086000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154600754600c5443030210611a935760075460086000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001548161195657fe5b04600c60008282540192505081905550600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060086000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611874565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a716b97f8360046040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff168152602001826005811115611b3857fe5b81526020019250505060206040518083038186803b158015611b5957600080fd5b505afa158015611b6d573d6000803e3d6000fd5b505050506040513d6020811015611b8357600080fd5b81019080805190602001909291905050509050919050565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166336214c7860006040518263ffffffff1660e01b815260040180826005811115611c0357fe5b815260200191505060206040518083038186803b158015611c2357600080fd5b505afa158015611c37573d6000803e3d6000fd5b505050506040513d6020811015611c4d57600080fd5b8101908080519060200190929190505050905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166336214c7860036040518263ffffffff1660e01b815260040180826005811115611cc357fe5b815260200191505060206040518083038186803b158015611ce357600080fd5b505afa158015611cf7573d6000803e3d6000fd5b505050506040513d6020811015611d0d57600080fd5b810190808051906020019092919050505090509056fe43757272656e746c79206e6f20696e7465726d656469617269657320616c6c6f77656420666f7220746869732066756e6374696f6e2063616c6c4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373496e73756666696369656e74207374616b6520746f2063616c6c206576656e206f6e6520626c6f636b6d73672e73656e646572206e6f7420617574686f72697a656420746f2064656c656761746520666f72207374616b6572436f756c64206e6f74206465706f736974207374616b652066756e6473202870657268617073206d616b6520616c6c6f77616e636520746f2066756e6420636f6e74726163743f496e73756666696369656e742066756e6473202d2d20736f6d657468696e672077656e74207265616c6c792077726f6e672ea2646970667358221220c52ae1617beca9024981e3aa50cc88efd87d430bdb977cb1e98bf07308e3cceb64736f6c63430007030033000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000aa4e3edb11afa93c41db59842b29de64b72e355b0000000000000000000000005fbdb2315678afecb367f032d93f642f64180aa3',
    r: '0xf697706dfcd1d470c43d8417f2975fc25d4096aa884182be9bdaa32d27bcf973',
    s: '0x1051a2b24bf2e636af73efd48d796aeb7eb873576a086c9c360fab7795ff1e58',
    v: 62709,
    creates: '0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9',
    chainId: 31337,
    wait: [Function (anonymous)]
  }
}
> 

Rename MarginTrading to CrossMarginTrading

Since we plan on supporting isolated margin we should

  • rename the contract MarginTrading
  • rename MarginAccount to CrossMarginAccount
  • Rename functions in MarginRouter to something like crossX, where X is the original function name

Add MFD

  • Copy mintable erc20 contract like dai
  • Issue MFD with bonds, upon request
  • have per-token MFD ratios

Use chainlink oracle

We want to create a contract satisfying this interface: https://github.com/marginswap/marginswap-core/blob/main/interfaces/IOracle.sol

In order to do so we need:

Call chainlink

write a function using this chainlink library: import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";

Here's a very rough sketch

address oracleAddress = tokenOracles[tokenAddress];
AggregatorV3Interface oracle = AggregatorV3Interface(oracleAddress);
        (
            uint80 roundID,
            int256 tokenPrice,
            uint256 startedAt,
            uint256 timeStamp,
            uint80 answeredInRound
        ) = oracle.latestRoundData();

return inAmount * tokenPrice * PEG_EXPONENT / oracleExponent[tokenADdress] / tokenExponent[tokenAddress];

This function likely would be a view function, so could be used to implement both the required functions of the interface.

Store metadata

We need a way to tell the contract which oracle to ask for each token, this should be a onlyOwnerExec gated function in the contract. It should store things such as the oracleExponent and tokenExponent as well as the address of teh oracle contract. You can find links to oracle contracts here

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.