@ethersproject/address#getContractAddress TypeScript Examples

The following examples show how to use @ethersproject/address#getContractAddress. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: task.ts    From balancer-v2-monorepo with GNU General Public License v3.0 5 votes vote down vote up
async check(name: string, args: Array<Param> = [], libs?: Libraries): Promise<Contract> {
    // There's multiple approaches to checking that a deployed contract matches known source code. A naive approach is
    // to check for a match in the runtime code, but that doesn't account for actions taken during  construction,
    // including calls, storage writes and setting immutable state variables. Since immutable state variables modify the
    // runtime code, it can be actually quite tricky to produce a matching runtime code.
    // What we do instead is check for both runtime code and constrcutor execution (including constructor arguments) by
    // looking at the transaction in which the contract was deployed. The data of said transaction will be the contract
    // creation code followed by the abi-encoded constructor arguments, which we can compare against what the task would
    // attempt to deploy. In this way, we are testing the task's build info, inputs and deployment code.
    // The only thing we're not checking is what account deployed the contract, but our code does not have dependencies
    // on the deployer.

    // The only problem with the approach described above is that it is not easy to find the transaction in which a
    // contract is deployed. Tenderly has a dedicated endpoint for this however.

    const { ethers } = await import('hardhat');

    const deployedAddress = this.output()[name];
    const deploymentTxHash = await getContractDeploymentTransactionHash(deployedAddress, this.network);
    const deploymentTx = await ethers.provider.getTransaction(deploymentTxHash);

    const expectedDeploymentAddress = getContractAddress(deploymentTx);
    if (deployedAddress !== expectedDeploymentAddress) {
      throw Error(
        `The stated deployment address of '${name}' on network '${this.network}' of task '${this.id}' does not match the address which would be deployed by the transaction ${deploymentTxHash} (${expectedDeploymentAddress})`
      );
    }

    if (deploymentTx.data === deploymentTxData(this.artifact(name), args, libs)) {
      logger.success(`Verified contract '${name}' on network '${this.network}' of task '${this.id}'`);
    } else {
      throw Error(
        `The build info and inputs for contract '${name}' on network '${this.network}' of task '${this.id}' does not match the data used to deploy address ${deployedAddress}`
      );
    }

    // We need to return an instance so that the task may carry on, potentially using this as input of future
    // deployments.
    return this.instanceAt(name, deployedAddress);
  }
Example #2
Source File: index.spec.ts    From forta-bot-sdk with MIT License 4 votes vote down vote up
describe("createTransactionEvent", () => {
  it("returns correctly formatted TransactionEvent", () => {
    const networkId = 1
    const jsonRpcTransaction = {
      "accessList": [],
      "blockHash": "0x550bf22138e7cd31602ecc180fac4e1d719ac52cfad41c8320078683a3b90859",
      "blockNumber": "0x5bad55",
      "chainId": "0x1",
      "from": "0xC9f7bc0Ed37b821A34bFD508059c75460d6EFB37",
      "gas": "0x249f0",
      "gasPrice": "0x174876e800",
      "hash": "0xfadb14c4d6bc7985583f6aded4d64bd0e071010ff4c29ab341a357550147fb28",
      "input": "0x530ed69400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000418ed8709d206b533ab0b6fc526987bff7ec7b5eae527062bb09af80f7f578231c0734276e7d4675fdf7c9fbe540578891cf9fac872d8663c7c634afb01c39f9931c00000000000000000000000000000000000000000000000000000000000000",
      "maxFeePerGas": "0x228a814e70",
      "maxPriorityFeePerGas": "0x59682f00",
      "nonce": "0x5e4724",
      "r": "0x2724a8ec2e2f3f634f04e954cf3b966bf9f734ada1611a44cd435441c83742e1",
      "s": "0x7ae8047b83dc285a32f9fe6fb0b84927fc789e2a411ea2616deb3efd7c77a9a2",
      "to": "0x0000000000000000000000000000000000000000",
      "transactionIndex": "0x0",
      "type": "0x2",
      "v": "0x0",
      "value": "400000000000000000"
    }
    const jsonRpcBlock = {
      "hash": "0x550bf22138e7cd31602ecc180fac4e1d719ac52cfad41c8320078683a3b90859",
      "number": "0x5bad55",
      "timestamp": "0x5b541449",
      "transactions": [jsonRpcTransaction],
    } as any
    const jsonRpcLog = {
      "address": "0xB9f7bc0Ed37b821A34bFD508059c75460d6EFB37",
      "topics": ["topic1"],
      "data": "0xdata",
      "logIndex": "0x1",
      "blockNumber": "0x5bad55",
      "blockHash": "0x550bf22138e7cd31602ecc180fac4e1d719ac52cfad41c8320078683a3b90859",
      "transactionIndex": "0x1",
      "transactionHash": "0xfadb14c4d6bc7985583f6aded4d64bd0e071010ff4c29ab341a357550147fb28",
      "removed": false
    }
    const traces: any = [{
      "blockHash": "0x550bf22138e7cd31602ecc180fac4e1d719ac52cfad41c8320078683a3b90859",
      "blockNumber": "0x5bad55",
      "result": {
        "gasUsed": "12345",
        "address": "0xC9f7bc0Ed37b821A34bFD508059c75460d6EFB37",
        "code": "1",
        "output": "0x01"
      },
      "action": {
        "callType": "someType",
        "to": "0xC9f7bc0Ed37b821A34bFD508059c75460d6EFB37",
        "input": "0xinput",
        "from": "0xc9F7bc0ed37b821A34bfd508069c75460d6efb37",
        "value": "500",
        "init": "xyz",
        "address": "0xC9f7bc0Ed37b821A34bFD508059c75460d6EFB38",
        "balance": "100",
        "refundAddress": "0xC9f7bc0Ed37b821A34bFD508059c75460d6EFB56"
      },
      "subtraces": 5,
      "traceAddress": [1, 2],
      "transactionHash": "0xfadb14c4d6bc7985583f6aded4d64bd0e071010ff4c29ab341a357550147fb28",
      "transactionPosition": 1,
      "type": "call",
      "error": ""
    }]

    const txEvent = createTransactionEvent(jsonRpcTransaction, jsonRpcBlock, networkId, traces, [jsonRpcLog])

    expect(txEvent).toBeInstanceOf(TransactionEvent)
    expect(txEvent.type).toEqual(EventType.BLOCK)
    expect(txEvent.network).toEqual(Network.MAINNET)
    expect(txEvent.transaction).toStrictEqual({
      hash: jsonRpcTransaction.hash,
      from: formatAddress(jsonRpcTransaction.from),
      to: formatAddress(jsonRpcTransaction.to),
      nonce: parseInt(jsonRpcTransaction.nonce),
      gas: jsonRpcTransaction.gas,
      gasPrice: jsonRpcTransaction.gasPrice,
      value: jsonRpcTransaction.value,
      data: jsonRpcTransaction.input,
      r: jsonRpcTransaction.r,
      s: jsonRpcTransaction.s,
      v: jsonRpcTransaction.v
    })
    expect(txEvent.logs).toStrictEqual([{
        address: formatAddress(jsonRpcLog.address),
        topics: jsonRpcLog.topics,
        data: jsonRpcLog.data,
        logIndex: parseInt(jsonRpcLog.logIndex),
        blockNumber: parseInt(jsonRpcLog.blockNumber),
        blockHash: jsonRpcLog.blockHash,
        transactionIndex: parseInt(jsonRpcLog.transactionIndex),
        transactionHash: jsonRpcLog.transactionHash,
        removed: jsonRpcLog.removed
      }
    ])
    expect(txEvent.traces).toStrictEqual(traces.map((trace: any) => ({
      action: {
        callType: trace.action.callType,
        to: formatAddress(trace.action.to),
        input: trace.action.input,
        from: formatAddress(trace.action.from),
        value: trace.action.value,
        init: trace.action.init,
        address: formatAddress(trace.action.address),
        balance: trace.action.balance,
        refundAddress: formatAddress(trace.action.refundAddress),
      },
      blockHash: trace.blockHash,
      blockNumber: trace.blockNumber,
      result: {
        gasUsed: trace.result.gasUsed,
        address: trace.result.address,
        code: trace.result.code,
        output: trace.result.output
      },
      subtraces: trace.subtraces,
      traceAddress: trace.traceAddress,
      transactionHash: trace.transactionHash,
      transactionPosition: trace.transactionPosition,
      type: trace.type,
      error: trace.error,
    })))
    const traceAction = traces[0].action
    expect(txEvent.addresses).toStrictEqual({
      [formatAddress(jsonRpcTransaction.from)]: true,
      [formatAddress(jsonRpcTransaction.to)]: true,
      [formatAddress(jsonRpcLog.address)]: true,
      [formatAddress(traceAction.address)]: true,
      [formatAddress(traceAction.refundAddress)]: true,
      [formatAddress(traceAction.to)]: true,
      [formatAddress(traceAction.from)]: true,
    })
    expect(txEvent.block).toStrictEqual({
      hash: jsonRpcBlock.hash,
      number: parseInt(jsonRpcBlock.number),
      timestamp: parseInt(jsonRpcBlock.timestamp)
    })
    expect(txEvent.contractAddress).toEqual(formatAddress(getContractAddress({ from: jsonRpcTransaction.from, nonce: jsonRpcTransaction.nonce })))
  })
})
Example #3
Source File: index.ts    From forta-bot-sdk with MIT License 4 votes vote down vote up
createTransactionEvent: CreateTransactionEvent = (
  transaction: JsonRpcTransaction, 
  block: JsonRpcBlock, 
  networkId: number, 
  traces: Trace[] = [],
  logs: JsonRpcLog[] = []
) => {
  const tx = {
    hash: transaction.hash,
    from: formatAddress(transaction.from),
    to: transaction.to ? formatAddress(transaction.to) : null,
    nonce: parseInt(transaction.nonce),
    gas: transaction.gas,
    gasPrice: transaction.gasPrice,
    value: transaction.value,
    data: transaction.input,
    r: transaction.r,
    s: transaction.s,
    v: transaction.v,
  }
  const addresses = {
    [tx.from]: true
  }
  if (tx.to) {
    addresses[tx.to] = true;
  }

  const blok = {
    hash: block.hash,
    number: parseInt(block.number),
    timestamp: parseInt(block.timestamp)
  }

  const trcs: Trace[] = []
  traces.forEach(trace => {
    addresses[formatAddress(trace.action.address)] = true
    addresses[formatAddress(trace.action.refundAddress)] = true
    addresses[formatAddress(trace.action.to)] = true
    addresses[formatAddress(trace.action.from)] = true

    trcs.push({
      action: {
        callType: trace.action.callType,
        to: formatAddress(trace.action.to),
        input: trace.action.input,
        from: formatAddress(trace.action.from),
        value: trace.action.value,
        init: trace.action.init,
        address: formatAddress(trace.action.address),
        balance: trace.action.balance,
        refundAddress: formatAddress(trace.action.refundAddress),
      },
      blockHash: trace.blockHash,
      blockNumber: trace.blockNumber,
      result: {
        gasUsed: trace.result?.gasUsed,
        address: trace.result?.address,
        code: trace.result?.code,
        output: trace.result?.output
      },
      subtraces: trace.subtraces,
      traceAddress: trace.traceAddress,
      transactionHash: trace.transactionHash,
      transactionPosition: trace.transactionPosition,
      type: trace.type,
      error: trace.error,
    })
  })

  const lgs = logs.map(log => ({
    address: formatAddress(log.address),
    topics: log.topics,
    data: log.data,
    logIndex: parseInt(log.logIndex),
    blockNumber: parseInt(log.blockNumber),
    blockHash: log.blockHash,
    transactionIndex: parseInt(log.transactionIndex),
    transactionHash: log.transactionHash,
    removed: log.removed,
  }))
  lgs.forEach(log => addresses[log.address] = true)

  let contractAddress = null
  if (isZeroAddress(transaction.to)) {
    contractAddress = formatAddress(getContractAddress({ from: transaction.from, nonce: transaction.nonce }))
  }

  return new TransactionEvent(
    EventType.BLOCK,
    networkId,
    tx,
    trcs,
    addresses,
    blok,
    lgs,
    contractAddress
  )
}