diff --git a/integration-tests/contracts/Address.sol b/integration-tests/contracts/Address.sol deleted file mode 100644 index 42a9dc1ebe9a1..0000000000000 --- a/integration-tests/contracts/Address.sol +++ /dev/null @@ -1,189 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.6.2 <0.8.0; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize, which returns 0 for contracts in - // construction, since the code is only stored at the end of the - // constructor execution. - - uint256 size; - // solhint-disable-next-line no-inline-assembly - assembly { size := extcodesize(account) } - return size > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - // solhint-disable-next-line avoid-low-level-calls, avoid-call-value - (bool success, ) = recipient.call{ value: amount }(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain`call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory returndata) = target.call{ value: value }(data); - return _verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory returndata) = target.staticcall(data); - return _verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory returndata) = target.delegatecall(data); - return _verifyCallResult(success, returndata, errorMessage); - } - - function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - - // solhint-disable-next-line no-inline-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} diff --git a/integration-tests/contracts/ChainlinkERC20.sol b/integration-tests/contracts/ChainlinkERC20.sol deleted file mode 100644 index b2c45df9567e7..0000000000000 --- a/integration-tests/contracts/ChainlinkERC20.sol +++ /dev/null @@ -1,207 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >0.6.0 <0.8.0; - -/** - * @title ERC20 - * @dev A super simple ERC20 implementation! - */ -contract ChainlinkERC20 { - - /********** - * Events * - **********/ - - event Transfer( - address indexed _from, - address indexed _to, - uint256 _value - ); - - event Approval( - address indexed _owner, - address indexed _spender, - uint256 _value - ); - - - /************* - * Variables * - *************/ - - mapping (address => uint256) public balances; - mapping (address => mapping (address => uint256)) public allowances; - - // Some optional extra goodies. - uint256 public totalSupply; - string public name; - - - /*************** - * Constructor * - ***************/ - - /** - * @param _initialSupply Initial maximum token supply. - * @param _name A name for our ERC20 (technically optional, but it's fun ok jeez). - */ - function init( - uint256 _initialSupply, - string memory _name - ) - public - { - balances[msg.sender] = _initialSupply; - totalSupply = _initialSupply; - name = _name; - } - - - /******************** - * Public Functions * - ********************/ - - /** - * Checks the balance of an address. - * @param _owner Address to check a balance for. - * @return Balance of the address. - */ - function balanceOf( - address _owner - ) - external - view - returns ( - uint256 - ) - { - return balances[_owner]; - } - - /** - * Transfers a balance from your account to someone else's account! - * @param _to Address to transfer a balance to. - * @param _amount Amount to transfer to the other account. - * @return true if the transfer was successful. - */ - function transfer( - address _to, - uint256 _amount - ) - external - returns ( - bool - ) - { - require( - balances[msg.sender] >= _amount, - "You don't have enough balance to make this transfer!" - ); - - balances[msg.sender] -= _amount; - balances[_to] += _amount; - - emit Transfer( - msg.sender, - _to, - _amount - ); - - return true; - } - - /** - * Transfers a balance from someone else's account to another account. You need an allowance - * from the sending account for this to work! - * @param _from Account to transfer a balance from. - * @param _to Account to transfer a balance to. - * @param _amount Amount to transfer to the other account. - * @return true if the transfer was successful. - */ - function transferFrom( - address _from, - address _to, - uint256 _amount - ) - external - returns ( - bool - ) - { - require( - balances[_from] >= _amount, - "Can't transfer from the desired account because it doesn't have enough balance." - ); - - require( - allowances[_from][msg.sender] >= _amount, - "Can't transfer from the desired account because you don't have enough of an allowance." - ); - - balances[_to] += _amount; - balances[_from] -= _amount; - - emit Transfer( - _from, - _to, - _amount - ); - - return true; - } - - /** - * Approves an account to spend some amount from your account. - * @param _spender Account to approve a balance for. - * @param _amount Amount to allow the account to spend from your account. - * @return true if the allowance was successful. - */ - function approve( - address _spender, - uint256 _amount - ) - external - returns ( - bool - ) - { - allowances[msg.sender][_spender] = _amount; - - emit Approval( - msg.sender, - _spender, - _amount - ); - - return true; - } - - /** - * Checks how much a given account is allowed to spend from another given account. - * @param _owner Address of the account to check an allowance from. - * @param _spender Address of the account trying to spend from the owner. - * @return Allowance for the spender from the owner. - */ - function allowance( - address _owner, - address _spender - ) - external - view - returns ( - uint256 - ) - { - return allowances[_owner][_spender]; - } - - function testRequire() - external - view - returns ( - uint256 - ) - { - require(false, "This is an revert string"); - return balances[msg.sender]; - } -} diff --git a/integration-tests/contracts/Initializable.sol b/integration-tests/contracts/Initializable.sol deleted file mode 100644 index d8d620126b4d0..0000000000000 --- a/integration-tests/contracts/Initializable.sol +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: MIT - -// solhint-disable-next-line compiler-version -pragma solidity >=0.4.24 <0.8.0; - -import "./Address.sol"; - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - */ -abstract contract Initializable { - - /** - * @dev Indicates that the contract has been initialized. - */ - bool private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Modifier to protect an initializer function from being invoked twice. - */ - modifier initializer() { - require(_initializing || _isConstructor() || !_initialized, "Initializable: contract is already initialized"); - - bool isTopLevelCall = !_initializing; - if (isTopLevelCall) { - _initializing = true; - _initialized = true; - } - - _; - - if (isTopLevelCall) { - _initializing = false; - } - } - - /// @dev Returns true if and only if the function is running in the constructor - function _isConstructor() private view returns (bool) { - return !Address.isContract(address(this)); - } -} diff --git a/integration-tests/contracts/UpgradeableProxy.sol b/integration-tests/contracts/UpgradeableProxy.sol deleted file mode 100644 index 40f24c879645b..0000000000000 --- a/integration-tests/contracts/UpgradeableProxy.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.6.0 <0.8.0; - -import "./Proxy.sol"; -import "./Address.sol"; - -/** - * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an - * implementation address that can be changed. This address is stored in storage in the location specified by - * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the - * implementation behind the proxy. - * - * Upgradeability is only provided internally through {_upgradeTo}. For an externally upgradeable proxy see - * {TransparentUpgradeableProxy}. - */ -contract UpgradeableProxy is Proxy { - /** - * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`. - * - * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded - * function call, and allows initializating the storage of the proxy like a Solidity constructor. - */ - constructor(address _logic, bytes memory _data) public payable { - assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1)); - _setImplementation(_logic); - if(_data.length > 0) { - Address.functionDelegateCall(_logic, _data); - } - } - - /** - * @dev Emitted when the implementation is upgraded. - */ - event Upgraded(address indexed implementation); - - /** - * @dev Storage slot with the address of the current implementation. - * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is - * validated in the constructor. - */ - bytes32 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; - - /** - * @dev Returns the current implementation address. - */ - function _implementation() internal view virtual override returns (address impl) { - bytes32 slot = _IMPLEMENTATION_SLOT; - // solhint-disable-next-line no-inline-assembly - assembly { - impl := sload(slot) - } - } - - /** - * @dev Upgrades the proxy to a new implementation. - * - * Emits an {Upgraded} event. - */ - function _upgradeTo(address newImplementation) internal virtual { - _setImplementation(newImplementation); - emit Upgraded(newImplementation); - } - - /** - * @dev Stores a new address in the EIP1967 implementation slot. - */ - function _setImplementation(address newImplementation) private { - require(Address.isContract(newImplementation), "UpgradeableProxy: new implementation is not a contract"); - - bytes32 slot = _IMPLEMENTATION_SLOT; - - // solhint-disable-next-line no-inline-assembly - assembly { - sstore(slot, newImplementation) - } - } -} diff --git a/integration-tests/test/erc20.spec.ts b/integration-tests/test/erc20.spec.ts deleted file mode 100644 index 248b5e1541b47..0000000000000 --- a/integration-tests/test/erc20.spec.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { Contract, ContractFactory, Wallet } from 'ethers' -import { ethers } from 'hardhat' -import { TxGasLimit, TxGasPrice } from '@eth-optimism/core-utils' -import chai, { expect } from 'chai' -import { GWEI } from './shared/utils' -import { OptimismEnv } from './shared/env' -import { solidity } from 'ethereum-waffle' - -chai.use(solidity) - -describe('Basic ERC20 interactions', async () => { - const initialAmount = 1000 - const tokenName = 'OVM Test' - const tokenDecimals = 8 - const TokenSymbol = 'OVM' - - let wallet: Wallet - let other: Wallet - let Factory__ERC20: ContractFactory - let ERC20: Contract - - before(async () => { - const env = await OptimismEnv.new() - wallet = env.l2Wallet - other = Wallet.createRandom().connect(ethers.provider) - Factory__ERC20 = await ethers.getContractFactory('ERC20', wallet) - }) - - beforeEach(async () => { - ERC20 = await Factory__ERC20.deploy( - initialAmount, - tokenName, - tokenDecimals, - TokenSymbol - ) - }) - - it('should set the total supply', async () => { - const totalSupply = await ERC20.totalSupply() - expect(totalSupply.toNumber()).to.equal(initialAmount) - }) - - it('should get the token name', async () => { - const name = await ERC20.name() - expect(name).to.equal(tokenName) - }) - - it('should get the token decimals', async () => { - const decimals = await ERC20.decimals() - expect(decimals).to.equal(tokenDecimals) - }) - - it('should get the token symbol', async () => { - const symbol = await ERC20.symbol() - expect(symbol).to.equal(TokenSymbol) - }) - - it('should assign initial balance', async () => { - const balance = await ERC20.balanceOf(wallet.address) - expect(balance.toNumber()).to.equal(initialAmount) - }) - - it('should transfer amount to destination account', async () => { - const transfer = await ERC20.transfer(other.address, 100) - const receipt = await transfer.wait() - - expect(receipt.events.length).to.equal(1) - expect(receipt.events[0].args._from).to.equal(wallet.address) - expect(receipt.events[0].args._value.toNumber()).to.equal(100) - - const receiverBalance = await ERC20.balanceOf(other.address) - const senderBalance = await ERC20.balanceOf(wallet.address) - - expect(receiverBalance.toNumber()).to.equal(100) - expect(senderBalance.toNumber()).to.equal(900) - }) - - it('should revert if trying to transfer too much', async () => { - await expect( - ERC20.transfer(other.address, initialAmount * 2) - ).to.be.revertedWith('insufficient balance') - }) -}) diff --git a/integration-tests/test/read-proxy-event.spec.ts b/integration-tests/test/read-proxy-event.spec.ts deleted file mode 100644 index 85ae6980e1806..0000000000000 --- a/integration-tests/test/read-proxy-event.spec.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { expect } from 'chai' -import { ethers } from 'hardhat' - -/* Imports: External */ -import { Contract, Wallet } from 'ethers' -import { OptimismEnv } from './shared/env' - -describe('Reading events from proxy contracts', () => { - let l2Wallet: Wallet - before(async () => { - const env = await OptimismEnv.new() - l2Wallet = env.l2Wallet - }) - - // helper to query the transfers - const _queryFilterTransfer = async ( - queryContract: Contract, - filterContract: Contract - ) => { - // Get the filter - const filter = filterContract.filters.Transfer(null, null, null) - // Query the filter - return queryContract.queryFilter(filter, 0, 'latest') - } - - let ProxyERC20: Contract - let ERC20: Contract - - beforeEach(async () => { - // Set up our contract factories in advance. - const Factory__ERC20 = await ethers.getContractFactory( - 'ChainlinkERC20', - l2Wallet - ) - const Factory__UpgradeableProxy = await ethers.getContractFactory( - 'UpgradeableProxy', - l2Wallet - ) - - // Deploy the underlying ERC20 implementation. - ERC20 = await Factory__ERC20.deploy() - await ERC20.deployTransaction.wait() - - // Deploy the upgradeable proxy and execute the init function. - ProxyERC20 = await Factory__UpgradeableProxy.deploy( - ERC20.address, - ERC20.interface.encodeFunctionData('init', [ - 1000, // initial supply - 'Cool Token Name Goes Here', // token name - ]) - ) - await ProxyERC20.deployTransaction.wait() - ProxyERC20 = new ethers.Contract( - ProxyERC20.address, - ERC20.interface, - l2Wallet - ) - }) - - it('should read transfer events from a proxy ERC20', async () => { - // Make two transfers. - const recipient = '0x0000000000000000000000000000000000000000' - const transfer1 = await ProxyERC20.transfer(recipient, 1) - await transfer1.wait() - const transfer2 = await ProxyERC20.transfer(recipient, 1) - await transfer2.wait() - - // Make sure events are being emitted in the right places. - expect((await _queryFilterTransfer(ERC20, ERC20)).length).to.eq(0) - expect((await _queryFilterTransfer(ERC20, ProxyERC20)).length).to.eq(0) - expect((await _queryFilterTransfer(ProxyERC20, ERC20)).length).to.eq(2) - expect((await _queryFilterTransfer(ProxyERC20, ProxyERC20)).length).to.eq(2) - }) -})