github.com/ethereum-optimism/optimism@v1.7.2/packages/sdk/test/utils/contracts.spec.ts (about)

     1  /* eslint-disable @typescript-eslint/no-empty-function */
     2  import { Signer } from 'ethers'
     3  import { ethers } from 'hardhat'
     4  
     5  import { expect } from '../setup'
     6  import {
     7    getOEContract,
     8    getAllOEContracts,
     9    CONTRACT_ADDRESSES,
    10    DEFAULT_L2_CONTRACT_ADDRESSES,
    11    L2ChainID,
    12  } from '../../src'
    13  
    14  describe('contract connection utils', () => {
    15    let signers: Signer[]
    16    before(async () => {
    17      signers = (await ethers.getSigners()) as any
    18    })
    19  
    20    describe('getOEContract', () => {
    21      describe('when given a known chain ID', () => {
    22        describe('when not given an address override', () => {
    23          it('should use the address for the given contract name and chain ID', () => {
    24            const addresses = CONTRACT_ADDRESSES[L2ChainID.OPTIMISM]
    25            for (const [contractName, contractAddress] of [
    26              ...Object.entries(addresses.l1),
    27              ...Object.entries(addresses.l2),
    28            ]) {
    29              const contract = getOEContract(
    30                contractName as any,
    31                L2ChainID.OPTIMISM
    32              )
    33              expect(contract.address).to.equal(contractAddress)
    34            }
    35          })
    36        })
    37  
    38        describe('when given an address override', () => {
    39          it('should use the custom address', () => {
    40            const addresses = CONTRACT_ADDRESSES[L2ChainID.OPTIMISM]
    41            for (const contractName of [
    42              ...Object.keys(addresses.l1),
    43              ...Object.keys(addresses.l2),
    44            ]) {
    45              const address = '0x' + '11'.repeat(20)
    46              const contract = getOEContract(contractName as any, 1, {
    47                address,
    48              })
    49              expect(contract.address).to.equal(address)
    50            }
    51          })
    52        })
    53      })
    54  
    55      describe('when given an unknown chain ID', () => {
    56        describe('when not given an address override', () => {
    57          it('should throw an error', () => {
    58            expect(() => getOEContract('L1CrossDomainMessenger', 3)).to.throw()
    59          })
    60        })
    61  
    62        describe('when given an address override', () => {
    63          it('should use the custom address', () => {
    64            const address = '0x' + '11'.repeat(20)
    65            const contract = getOEContract('L1CrossDomainMessenger', 3, {
    66              address,
    67            })
    68            expect(contract.address).to.equal(address)
    69          })
    70        })
    71      })
    72  
    73      describe('when connected to a valid address', () => {
    74        it('should have the correct interface for the contract name', () => {
    75          const contract = getOEContract(
    76            'L1CrossDomainMessenger',
    77            L2ChainID.OPTIMISM
    78          )
    79          expect(contract.sendMessage).to.not.be.undefined
    80        })
    81  
    82        describe('when not given a signer or provider', () => {
    83          it('should not have a signer or provider', () => {
    84            const contract = getOEContract(
    85              'L1CrossDomainMessenger',
    86              L2ChainID.OPTIMISM
    87            )
    88            expect(contract.signer).to.be.null
    89            expect(contract.provider).to.be.null
    90          })
    91        })
    92  
    93        describe('when given a signer', () => {
    94          it('should attach the given signer', () => {
    95            const contract = getOEContract(
    96              'L1CrossDomainMessenger',
    97              L2ChainID.OPTIMISM,
    98              {
    99                signerOrProvider: signers[0],
   100              }
   101            )
   102            expect(contract.signer).to.deep.equal(signers[0])
   103          })
   104        })
   105  
   106        describe('when given a provider', () => {
   107          it('should attach the given provider', () => {
   108            const contract = getOEContract(
   109              'L1CrossDomainMessenger',
   110              L2ChainID.OPTIMISM,
   111              {
   112                signerOrProvider: ethers.provider as any,
   113              }
   114            )
   115            expect(contract.signer).to.be.null
   116            expect(contract.provider).to.deep.equal(ethers.provider)
   117          })
   118        })
   119      })
   120    })
   121  
   122    describe('getAllOEContracts', () => {
   123      describe('when given a known chain ID', () => {
   124        describe('when not given any address overrides', () => {
   125          it('should return all contracts connected to the default addresses', () => {
   126            const contracts = getAllOEContracts(L2ChainID.OPTIMISM)
   127            const addresses = CONTRACT_ADDRESSES[L2ChainID.OPTIMISM]
   128            for (const [contractName, contractAddress] of Object.entries(
   129              addresses.l1
   130            )) {
   131              const contract = contracts.l1[contractName]
   132              expect(contract.address).to.equal(contractAddress)
   133            }
   134            for (const [contractName, contractAddress] of Object.entries(
   135              addresses.l2
   136            )) {
   137              const contract = contracts.l2[contractName]
   138              expect(contract.address).to.equal(contractAddress)
   139            }
   140          })
   141        })
   142  
   143        describe('when given address overrides', () => {
   144          it('should return contracts connected to the overridden addresses where given', () => {
   145            const overrides = {
   146              l1: {
   147                L1CrossDomainMessenger: '0x' + '11'.repeat(20),
   148              },
   149              l2: {
   150                L2CrossDomainMessenger: '0x' + '22'.repeat(20),
   151              },
   152            }
   153            const contracts = getAllOEContracts(L2ChainID.OPTIMISM, { overrides })
   154            const addresses = CONTRACT_ADDRESSES[L2ChainID.OPTIMISM]
   155            for (const [contractName, contractAddress] of Object.entries(
   156              addresses.l1
   157            )) {
   158              const contract = contracts.l1[contractName]
   159              if (overrides.l1[contractName]) {
   160                expect(contract.address).to.equal(overrides.l1[contractName])
   161              } else {
   162                expect(contract.address).to.equal(contractAddress)
   163              }
   164            }
   165            for (const [contractName, contractAddress] of Object.entries(
   166              addresses.l2
   167            )) {
   168              const contract = contracts.l2[contractName]
   169              if (overrides.l2[contractName]) {
   170                expect(contract.address).to.equal(overrides.l2[contractName])
   171              } else {
   172                expect(contract.address).to.equal(contractAddress)
   173              }
   174            }
   175          })
   176        })
   177      })
   178  
   179      describe('when given an unknown chain ID', () => {
   180        describe('when given address overrides for all L1 contracts', () => {
   181          describe('when given address overrides for L2 contracts', () => {
   182            it('should return contracts connected to the overridden addresses where given', () => {
   183              const l1Overrides = {}
   184              for (const contractName of Object.keys(
   185                CONTRACT_ADDRESSES[L2ChainID.OPTIMISM].l1
   186              )) {
   187                l1Overrides[contractName] = '0x' + '11'.repeat(20)
   188              }
   189  
   190              const contracts = getAllOEContracts(3, {
   191                overrides: {
   192                  l1: l1Overrides as any,
   193                  l2: {
   194                    L2CrossDomainMessenger: '0x' + '22'.repeat(20),
   195                  },
   196                },
   197              })
   198  
   199              for (const [contractName, contract] of Object.entries(
   200                contracts.l1
   201              )) {
   202                expect(contract.address).to.equal(l1Overrides[contractName])
   203              }
   204  
   205              expect(contracts.l2.L2CrossDomainMessenger.address).to.equal(
   206                '0x' + '22'.repeat(20)
   207              )
   208            })
   209          })
   210  
   211          describe('when not given address overrides for L2 contracts', () => {
   212            it('should return contracts connected to the default L2 addresses and custom L1 addresses', () => {
   213              const l1Overrides = {}
   214              for (const contractName of Object.keys(
   215                CONTRACT_ADDRESSES[L2ChainID.OPTIMISM].l1
   216              )) {
   217                l1Overrides[contractName] = '0x' + '11'.repeat(20)
   218              }
   219  
   220              const contracts = getAllOEContracts(3, {
   221                overrides: {
   222                  l1: l1Overrides as any,
   223                },
   224              })
   225  
   226              for (const [contractName, contract] of Object.entries(
   227                contracts.l1
   228              )) {
   229                expect(contract.address).to.equal(l1Overrides[contractName])
   230              }
   231  
   232              for (const [contractName, contract] of Object.entries(
   233                contracts.l2
   234              )) {
   235                expect(contract.address).to.equal(
   236                  DEFAULT_L2_CONTRACT_ADDRESSES[contractName]
   237                )
   238              }
   239            })
   240          })
   241        })
   242  
   243        describe('when given address overrides for some L1 contracts', () => {
   244          it('should throw an error', () => {
   245            expect(() =>
   246              getAllOEContracts(3, {
   247                overrides: {
   248                  l1: {
   249                    L1CrossDomainMessenger: '0x' + '11'.repeat(20),
   250                  },
   251                },
   252              })
   253            ).to.throw()
   254          })
   255        })
   256  
   257        describe('when given address overrides for no L1 contracts', () => {
   258          it('should throw an error', () => {
   259            expect(() => getAllOEContracts(3)).to.throw()
   260          })
   261        })
   262      })
   263  
   264      describe('when not given a signer or provider', () => {
   265        it('should not attach a signer or provider to any contracts', () => {
   266          const contracts = getAllOEContracts(L2ChainID.OPTIMISM)
   267          for (const contract of Object.values(contracts.l1)) {
   268            expect(contract.signer).to.be.null
   269            expect(contract.provider).to.be.null
   270          }
   271          for (const contract of Object.values(contracts.l2)) {
   272            expect(contract.signer).to.be.null
   273            expect(contract.provider).to.be.null
   274          }
   275        })
   276      })
   277  
   278      describe('when given an L1 signer', () => {
   279        it('should attach the signer to the L1 contracts only', () => {
   280          const contracts = getAllOEContracts(L2ChainID.OPTIMISM, {
   281            l1SignerOrProvider: signers[0],
   282          })
   283          for (const contract of Object.values(contracts.l1)) {
   284            expect(contract.signer).to.deep.equal(signers[0])
   285          }
   286          for (const contract of Object.values(contracts.l2)) {
   287            expect(contract.signer).to.be.null
   288            expect(contract.provider).to.be.null
   289          }
   290        })
   291      })
   292  
   293      describe('when given an L2 signer', () => {
   294        it('should attach the signer to the L2 contracts only', () => {
   295          const contracts = getAllOEContracts(L2ChainID.OPTIMISM, {
   296            l2SignerOrProvider: signers[0],
   297          })
   298          for (const contract of Object.values(contracts.l1)) {
   299            expect(contract.signer).to.be.null
   300            expect(contract.provider).to.be.null
   301          }
   302          for (const contract of Object.values(contracts.l2)) {
   303            expect(contract.signer).to.deep.equal(signers[0])
   304          }
   305        })
   306      })
   307  
   308      describe('when given an L1 signer and an L2 signer', () => {
   309        it('should attach the signer to both sets of contracts', () => {
   310          const contracts = getAllOEContracts(L2ChainID.OPTIMISM, {
   311            l1SignerOrProvider: signers[0],
   312            l2SignerOrProvider: signers[1],
   313          })
   314          for (const contract of Object.values(contracts.l1)) {
   315            expect(contract.signer).to.deep.equal(signers[0])
   316          }
   317          for (const contract of Object.values(contracts.l2)) {
   318            expect(contract.signer).to.deep.equal(signers[1])
   319          }
   320        })
   321      })
   322  
   323      describe('when given an L1 provider', () => {
   324        it('should attach the provider to the L1 contracts only', () => {
   325          const contracts = getAllOEContracts(L2ChainID.OPTIMISM, {
   326            l1SignerOrProvider: ethers.provider as any,
   327          })
   328          for (const contract of Object.values(contracts.l1)) {
   329            expect(contract.signer).to.be.null
   330            expect(contract.provider).to.deep.equal(ethers.provider)
   331          }
   332          for (const contract of Object.values(contracts.l2)) {
   333            expect(contract.signer).to.be.null
   334            expect(contract.provider).to.be.null
   335          }
   336        })
   337      })
   338  
   339      describe('when given an L2 provider', () => {
   340        it('should attach the provider to the L2 contracts only', () => {
   341          const contracts = getAllOEContracts(L2ChainID.OPTIMISM, {
   342            l2SignerOrProvider: ethers.provider as any,
   343          })
   344          for (const contract of Object.values(contracts.l1)) {
   345            expect(contract.signer).to.be.null
   346            expect(contract.provider).to.be.null
   347          }
   348          for (const contract of Object.values(contracts.l2)) {
   349            expect(contract.signer).to.be.null
   350            expect(contract.provider).to.deep.equal(ethers.provider)
   351          }
   352        })
   353      })
   354  
   355      describe('when given an L1 provider and an L2 provider', () => {
   356        it('should attach the provider to both sets of contracts', () => {
   357          const contracts = getAllOEContracts(L2ChainID.OPTIMISM, {
   358            l1SignerOrProvider: ethers.provider as any,
   359            l2SignerOrProvider: ethers.provider as any,
   360          })
   361          for (const contract of Object.values(contracts.l1)) {
   362            expect(contract.signer).to.be.null
   363            expect(contract.provider).to.deep.equal(ethers.provider)
   364          }
   365          for (const contract of Object.values(contracts.l2)) {
   366            expect(contract.signer).to.be.null
   367            expect(contract.provider).to.deep.equal(ethers.provider)
   368          }
   369        })
   370      })
   371    })
   372  })