Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion integration-tests/contracts/ERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ contract ERC20 {

function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
uint256 allowance = allowed[_from][msg.sender];
require(balances[_from] >= _value && allowance >= _value);
require(balances[_from] >= _value && allowance >= _value, "bad allowance");
balances[_to] += _value;
balances[_from] -= _value;
if (allowance < MAX_UINT256) {
Expand All @@ -65,4 +65,8 @@ contract ERC20 {
function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
return allowed[_owner][_spender];
}

function destroy() public {
selfdestruct(payable(msg.sender));
}
}
26 changes: 17 additions & 9 deletions integration-tests/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,26 @@ const config: HardhatUserConfig = {
timeout: isLiveNetwork() ? 300_000 : 75_000,
},
solidity: {
version: '0.8.9',
settings: {
optimizer: { enabled: true, runs: 200 },
metadata: {
bytecodeHash: 'none',
compilers: [
{
version: '0.7.6',
settings: {},
},
outputSelection: {
'*': {
'*': ['storageLayout'],
{
version: '0.8.9',
settings: {
optimizer: { enabled: true, runs: 200 },
metadata: {
bytecodeHash: 'none',
},
outputSelection: {
'*': {
'*': ['storageLayout'],
},
},
},
},
},
],
},
gasReporter: {
enabled: enableGasReport,
Expand Down
6 changes: 5 additions & 1 deletion integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
"@types/shelljs": "^0.8.8",
"@typescript-eslint/eslint-plugin": "^4.26.0",
"@typescript-eslint/parser": "^4.26.0",
"@uniswap/v3-core": "1.0.0",
"@uniswap/v3-periphery": "^1.0.1",
"@uniswap/v3-sdk": "^3.6.2",
"babel-eslint": "^10.1.0",
"chai": "^4.3.4",
"chai-as-promised": "^7.1.1",
Expand All @@ -50,10 +53,11 @@
"ethers": "^5.4.5",
"hardhat": "^2.3.0",
"hardhat-gas-reporter": "^1.0.4",
"lint-staged": "11.0.0",
"mocha": "^8.4.0",
"rimraf": "^3.0.2",
"shelljs": "^0.8.4",
"typescript": "^4.3.5",
"lint-staged": "11.0.0"
"uniswap-v3-deploy-plugin": "^0.1.0"
}
}
2 changes: 1 addition & 1 deletion integration-tests/sync-tests/1-sync-verifier.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import chai, { expect } from 'chai'
import { expect } from 'chai'
import { Wallet, BigNumber, providers } from 'ethers'
import { injectL2Context } from '@eth-optimism/core-utils'

Expand Down
2 changes: 1 addition & 1 deletion integration-tests/sync-tests/2-sync-replica.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import chai, { expect } from 'chai'
import { expect } from 'chai'
import { Wallet, Contract, ContractFactory, providers } from 'ethers'
import { ethers } from 'hardhat'
import { injectL2Context } from '@eth-optimism/core-utils'
Expand Down
3 changes: 1 addition & 2 deletions integration-tests/test/basic-l1-l2-communication.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@ import { expect } from 'chai'

/* Imports: External */
import { Contract, ContractFactory } from 'ethers'
import { applyL1ToL2Alias } from '@eth-optimism/core-utils'
import { applyL1ToL2Alias, awaitCondition } from '@eth-optimism/core-utils'

/* Imports: Internal */
import simpleStorageJson from '../artifacts/contracts/SimpleStorage.sol/SimpleStorage.json'
import l2ReverterJson from '../artifacts/contracts/Reverter.sol/Reverter.json'
import { Direction } from './shared/watcher-utils'
import { OptimismEnv } from './shared/env'
import { awaitCondition } from '@eth-optimism/core-utils'

describe('Basic L1<>L2 Communication', async () => {
let Factory__L1SimpleStorage: ContractFactory
Expand Down
205 changes: 205 additions & 0 deletions integration-tests/test/contracts.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
import { BigNumber, Contract, ContractFactory, utils, Wallet } from 'ethers'
import { ethers } from 'hardhat'
import { solidity } from 'ethereum-waffle'
import chai, { expect } from 'chai'
import { UniswapV3Deployer } from 'uniswap-v3-deploy-plugin/dist/deployer/UniswapV3Deployer'

import { OptimismEnv } from './shared/env'
import { FeeAmount, TICK_SPACINGS } from '@uniswap/v3-sdk'

chai.use(solidity)

// Below methods taken from the Uniswap test suite, see
// https://github.com/Uniswap/v3-periphery/blob/main/test/shared/ticks.ts
const getMinTick = (tickSpacing: number) =>
Math.ceil(-887272 / tickSpacing) * tickSpacing
const getMaxTick = (tickSpacing: number) =>
Math.floor(887272 / tickSpacing) * tickSpacing

describe('Contract interactions', () => {
let env: OptimismEnv

let Factory__ERC20: ContractFactory

let otherWallet: Wallet

before(async () => {
env = await OptimismEnv.new()

Factory__ERC20 = await ethers.getContractFactory('ERC20', env.l2Wallet)

otherWallet = Wallet.createRandom().connect(env.l2Wallet.provider)
await env.l2Wallet.sendTransaction({
to: otherWallet.address,
value: utils.parseEther('0.1'),
})
})

describe('ERC20s', () => {
let contract: Contract

before(async () => {
Factory__ERC20 = await ethers.getContractFactory('ERC20', env.l2Wallet)
})

it('should successfully deploy the contract', async () => {
contract = await Factory__ERC20.deploy(100000000, 'OVM Test', 8, 'OVM')
await contract.deployed()
})

it('should support approvals', async () => {
const spender = '0x' + '22'.repeat(20)
const tx = await contract.approve(spender, 1000)
await tx.wait()
let allowance = await contract.allowance(env.l2Wallet.address, spender)
expect(allowance).to.deep.equal(BigNumber.from(1000))
allowance = await contract.allowance(otherWallet.address, spender)
expect(allowance).to.deep.equal(BigNumber.from(0))

const logs = await contract.queryFilter(
contract.filters.Approval(env.l2Wallet.address),
1,
'latest'
)
expect(logs[0].args._owner).to.equal(env.l2Wallet.address)
expect(logs[0].args._spender).to.equal(spender)
expect(logs[0].args._value).to.deep.equal(BigNumber.from(1000))
})

it('should support transferring balances', async () => {
const tx = await contract.transfer(otherWallet.address, 1000)
await tx.wait()
const balFrom = await contract.balanceOf(env.l2Wallet.address)
const balTo = await contract.balanceOf(otherWallet.address)
expect(balFrom).to.deep.equal(BigNumber.from(100000000).sub(1000))
expect(balTo).to.deep.equal(BigNumber.from(1000))

const logs = await contract.queryFilter(
contract.filters.Transfer(env.l2Wallet.address),
1,
'latest'
)
expect(logs[0].args._from).to.equal(env.l2Wallet.address)
expect(logs[0].args._to).to.equal(otherWallet.address)
expect(logs[0].args._value).to.deep.equal(BigNumber.from(1000))
})

it('should support being self destructed', async () => {
const tx = await contract.destroy()
await tx.wait()
const code = await env.l2Wallet.provider.getCode(contract.address)
expect(code).to.equal('0x')
})
})

describe('uniswap', () => {
let contracts: { [name: string]: Contract }
let tokens: Contract[]

before(async () => {
const tokenA = await Factory__ERC20.deploy(100000000, 'OVM1', 8, 'OVM1')
await tokenA.deployed()
const tokenB = await Factory__ERC20.deploy(100000000, 'OVM2', 8, 'OVM2')
await tokenB.deployed()
tokens = [tokenA, tokenB]
tokens.sort((a, b) => {
if (a.address > b.address) {
return 1
}

if (a.address < b.address) {
return -1
}

return 0
})

const tx = await tokens[0].transfer(otherWallet.address, 100000)
await tx.wait()
})

it('should deploy the Uniswap ecosystem', async () => {
contracts = await UniswapV3Deployer.deploy(env.l2Wallet)
})

it('should deploy and initialize a liquidity pool', async () => {
const tx =
await contracts.positionManager.createAndInitializePoolIfNecessary(
tokens[0].address,
tokens[1].address,
FeeAmount.MEDIUM,
// initial ratio of 1/1
BigNumber.from('79228162514264337593543950336')
)
await tx.wait()
})

it('should approve the contracts', async () => {
for (const wallet of [env.l2Wallet, otherWallet]) {
for (const token of tokens) {
let tx = await token
.connect(wallet)
.approve(contracts.positionManager.address, 100000000)
await tx.wait()
tx = await token
.connect(wallet)
.approve(contracts.router.address, 100000000)
await tx.wait()
}
}
})

it('should mint new positions', async () => {
const tx = await contracts.positionManager.mint(
{
token0: tokens[0].address,
token1: tokens[1].address,
tickLower: getMinTick(TICK_SPACINGS[FeeAmount.MEDIUM]),
tickUpper: getMaxTick(TICK_SPACINGS[FeeAmount.MEDIUM]),
fee: FeeAmount.MEDIUM,
recipient: env.l2Wallet.address,
amount0Desired: 15,
amount1Desired: 15,
amount0Min: 0,
amount1Min: 0,
deadline: Date.now() * 2,
},
{
gasLimit: 10000000,
}
)
await tx.wait()
expect(
await contracts.positionManager.balanceOf(env.l2Wallet.address)
).to.eq(1)
expect(
await contracts.positionManager.tokenOfOwnerByIndex(
env.l2Wallet.address,
0
)
).to.eq(1)
})

it('should swap', async () => {
const tx = await contracts.router.connect(otherWallet).exactInputSingle(
{
tokenIn: tokens[0].address,
tokenOut: tokens[1].address,
fee: FeeAmount.MEDIUM,
recipient: otherWallet.address,
deadline: Date.now() * 2,
amountIn: 10,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0,
},
{
gasLimit: 10000000,
}
)
await tx.wait()
expect(await tokens[1].balanceOf(otherWallet.address)).to.deep.equal(
BigNumber.from('5')
)
})
})
})
16 changes: 0 additions & 16 deletions integration-tests/test/shared/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,22 +174,6 @@ export const waitForL2Geth = async (
return injectL2Context(provider)
}

export const awaitCondition = async (
cond: () => Promise<boolean>,
rate = 1000,
attempts = 10
) => {
for (let i = 0; i < attempts; i++) {
const ok = await cond()
if (ok) {
return
}

await sleep(rate)
}
throw new Error('Timed out.')
}

export const gasPriceForL2 = async () => {
if (isLiveNetwork()) {
return Promise.resolve(BigNumber.from(10000))
Expand Down
32 changes: 32 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3192,6 +3192,19 @@
tiny-invariant "^1.1.0"
tiny-warning "^1.0.3"

"@uniswap/v3-sdk@^3.6.2":
version "3.6.2"
resolved "https://registry.yarnpkg.com/@uniswap/v3-sdk/-/v3-sdk-3.6.2.tgz#45fa659f7642e8807cb36939e4426355c7a5943c"
integrity sha512-RHJaFfO6+ugI0+v0xhGXuVadmJ9bTbAz/RnuS/xRpXrRIsLNRVC42bYZ3Ci0JPWhkaNygCcc3LJ36Bs6GganSg==
dependencies:
"@ethersproject/abi" "^5.0.12"
"@ethersproject/solidity" "^5.0.9"
"@uniswap/sdk-core" "^3.0.1"
"@uniswap/v3-periphery" "^1.1.1"
"@uniswap/v3-staker" "1.0.0"
tiny-invariant "^1.1.0"
tiny-warning "^1.0.3"

"@uniswap/v3-staker@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@uniswap/v3-staker/-/v3-staker-1.0.0.tgz#9a6915ec980852479dfc903f50baf822ff8fa66e"
Expand Down Expand Up @@ -5094,6 +5107,16 @@ cli-table3@^0.5.0:
optionalDependencies:
colors "^1.1.2"

cli-table3@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.0.tgz#b7b1bc65ca8e7b5cef9124e13dc2b21e2ce4faee"
integrity sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ==
dependencies:
object-assign "^4.1.0"
string-width "^4.2.0"
optionalDependencies:
colors "^1.1.2"

cli-table@^0.3.1:
version "0.3.6"
resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.6.tgz#e9d6aa859c7fe636981fd3787378c2a20bce92fc"
Expand Down Expand Up @@ -15258,6 +15281,15 @@ unique-slug@^2.0.0:
dependencies:
imurmurhash "^0.1.4"

uniswap-v3-deploy-plugin@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/uniswap-v3-deploy-plugin/-/uniswap-v3-deploy-plugin-0.1.0.tgz#dd1798106373c16108aa2b5a0ec3b176c5c51d43"
integrity sha512-goowszquDWierss0oCB91MoQY2W1ue1fixA7XrxPQbVU0pt7ZGUv2KvxqYtcjpey9AcJrveGJoGYvpSLxmkzaw==
dependencies:
"@uniswap/v3-core" "1.0.0"
"@uniswap/v3-periphery" "^1.0.1"
cli-table3 "^0.6.0"

universal-user-agent@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee"
Expand Down