forked from ethereum-optimism/optimism
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test(integration-tests): ovmCALL-types with value (compiler and wrapper)
* fix ovmDELEGATECALL type, update tests * add ovmSELFBALANCE * fix ovmDELEGATECALL jumping to CALL * chore: lint
- Loading branch information
Showing
13 changed files
with
377 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// SPDX-License-Identifier: MIT | ||
// @unsupported: evm | ||
pragma solidity >=0.7.0; | ||
|
||
contract ValueCallsWithCompiler { | ||
|
||
receive() external payable { } | ||
|
||
function getBalance( | ||
address _address | ||
) external payable returns(uint256) { | ||
return _address.balance; | ||
} | ||
|
||
function simpleSend( | ||
address _address, | ||
uint _value | ||
) external payable returns (bool, bytes memory) { | ||
return sendWithData(_address, _value, hex""); | ||
} | ||
|
||
function sendWithData( | ||
address _address, | ||
uint _value, | ||
bytes memory _calldata | ||
) public returns (bool, bytes memory) { | ||
return _address.call{value: _value}(_calldata); | ||
} | ||
|
||
function verifyCallValueAndRevert( | ||
uint256 _expectedValue | ||
) external payable { | ||
bool correct = _checkCallValue(_expectedValue); | ||
// do the opposite of expected if the value is wrong. | ||
if (correct) { | ||
revert("expected revert"); | ||
} else { | ||
return; | ||
} | ||
} | ||
|
||
function getCallValue() public payable returns(uint256) { | ||
return msg.value; | ||
} | ||
|
||
function verifyCallValueAndReturn( | ||
uint256 _expectedValue | ||
) external payable { | ||
bool correct = _checkCallValue(_expectedValue); | ||
// do the opposite of expected if the value is wrong. | ||
if (correct) { | ||
return; | ||
} else { | ||
revert("unexpected revert"); | ||
} | ||
} | ||
|
||
function _checkCallValue( | ||
uint256 _expectedValue | ||
) internal returns(bool) { | ||
return getCallValue() == _expectedValue; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// SPDX-License-Identifier: MIT | ||
// @unsupported: evm | ||
pragma solidity >=0.7.0; | ||
|
||
import { Lib_ExecutionManagerWrapper } from "@eth-optimism/contracts/contracts/optimistic-ethereum/libraries/wrappers/Lib_ExecutionManagerWrapper.sol"; | ||
|
||
contract ValueCallsWithWrapper { | ||
|
||
receive() external payable { } | ||
|
||
function getBalance( | ||
address _address | ||
) external payable returns(uint256) { | ||
return Lib_ExecutionManagerWrapper.ovmBALANCE(_address); | ||
} | ||
|
||
function simpleSend( | ||
address _address, | ||
uint _value | ||
) external payable returns (bool, bytes memory) { | ||
return sendWithData(_address, _value, hex""); | ||
} | ||
|
||
function sendWithData( | ||
address _address, | ||
uint _value, | ||
bytes memory _calldata | ||
) public returns (bool, bytes memory) { | ||
return Lib_ExecutionManagerWrapper.ovmCALL(gasleft(), _address, _value, _calldata); | ||
} | ||
|
||
function verifyCallValueAndRevert( | ||
uint256 _expectedValue | ||
) external payable { | ||
bool correct = _checkCallValue(_expectedValue); | ||
// do the opposite of expected if the value is wrong. | ||
if (correct) { | ||
revert("expected revert"); | ||
} else { | ||
return; | ||
} | ||
} | ||
|
||
function getCallValue() public payable returns(uint256) { | ||
return Lib_ExecutionManagerWrapper.ovmCALLVALUE(); | ||
} | ||
|
||
function verifyCallValueAndReturn( | ||
uint256 _expectedValue | ||
) external payable { | ||
bool correct = _checkCallValue(_expectedValue); | ||
// do the opposite of expected if the value is wrong. | ||
if (correct) { | ||
return; | ||
} else { | ||
revert("unexpected revert"); | ||
} | ||
} | ||
|
||
function _checkCallValue( | ||
uint256 _expectedValue | ||
) internal returns(bool) { | ||
return getCallValue() == _expectedValue; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import { BigNumber, Contract, ContractFactory, Wallet } from 'ethers' | ||
import { ethers } from 'hardhat' | ||
import chai, { expect } from 'chai' | ||
import { GWEI, fundUser, encodeSolidityRevertMessage } from './shared/utils' | ||
import { OptimismEnv } from './shared/env' | ||
import { solidity } from 'ethereum-waffle' | ||
|
||
chai.use(solidity) | ||
|
||
for (const sourceName of ['ValueCallsWithWrapper', 'ValueCallsWithCompiler']) { | ||
describe(`OVM calls with native ETH value (${sourceName})`, async () => { | ||
const initialBalance0 = 42000 | ||
|
||
let env: OptimismEnv | ||
let wallet: Wallet | ||
let other: Wallet | ||
let Factory__ValueCalls: ContractFactory | ||
let ValueCalls0: Contract | ||
let ValueCalls1: Contract | ||
|
||
const checkBalances = async (expectedBalances: number[]) => { | ||
// query geth as one check | ||
const balance0 = await wallet.provider.getBalance(ValueCalls0.address) | ||
const balance1 = await wallet.provider.getBalance(ValueCalls1.address) | ||
expect(balance0).to.deep.eq(BigNumber.from(expectedBalances[0])) | ||
expect(balance1).to.deep.eq(BigNumber.from(expectedBalances[1])) | ||
// also use ovmBALANCE() opcode via eth_call | ||
const ovmBALANCE0 = await ValueCalls0.callStatic.getBalance( | ||
ValueCalls0.address | ||
) | ||
const ovmBALANCE1 = await ValueCalls0.callStatic.getBalance( | ||
ValueCalls1.address | ||
) | ||
expect(ovmBALANCE0).to.deep.eq(BigNumber.from(expectedBalances[0])) | ||
expect(ovmBALANCE1).to.deep.eq(BigNumber.from(expectedBalances[1])) | ||
} | ||
|
||
before(async () => { | ||
env = await OptimismEnv.new() | ||
wallet = env.l2Wallet | ||
other = Wallet.createRandom().connect(ethers.provider) | ||
Factory__ValueCalls = await ethers.getContractFactory(sourceName, wallet) | ||
}) | ||
|
||
beforeEach(async () => { | ||
ValueCalls0 = await Factory__ValueCalls.deploy() | ||
ValueCalls1 = await Factory__ValueCalls.deploy() | ||
await fundUser( | ||
env.watcher, | ||
env.gateway, | ||
initialBalance0, | ||
ValueCalls0.address | ||
) | ||
// These tests ass assume ValueCalls0 starts with a balance, but ValueCalls1 does not. | ||
await checkBalances([initialBalance0, 0]) | ||
}) | ||
|
||
it('should allow ETH to be sent', async () => { | ||
const sendAmount = 15 | ||
const tx = await ValueCalls0.simpleSend(ValueCalls1.address, sendAmount, { | ||
gasPrice: 0, | ||
}) | ||
await tx.wait() | ||
await checkBalances([initialBalance0 - sendAmount, sendAmount]) | ||
}) | ||
|
||
it('should allow ETH to be sent and have the correct ovmCALLVALUE', async () => { | ||
const sendAmount = 15 | ||
const [success, returndata] = await ValueCalls0.callStatic.sendWithData( | ||
ValueCalls1.address, | ||
sendAmount, | ||
ValueCalls1.interface.encodeFunctionData('getCallValue') | ||
) | ||
|
||
expect(success).to.be.true | ||
expect(BigNumber.from(returndata)).to.deep.eq(BigNumber.from(sendAmount)) | ||
}) | ||
|
||
it('should have the correct callvalue but not persist the transfer if the target reverts', async () => { | ||
const sendAmount = 15 | ||
const internalCalldata = ValueCalls1.interface.encodeFunctionData( | ||
'verifyCallValueAndRevert', | ||
[sendAmount] | ||
) | ||
const [success, returndata] = await ValueCalls0.callStatic.sendWithData( | ||
ValueCalls1.address, | ||
sendAmount, | ||
internalCalldata | ||
) | ||
|
||
expect(success).to.be.false | ||
expect(returndata).to.eq(encodeSolidityRevertMessage('expected revert')) | ||
|
||
await checkBalances([initialBalance0, 0]) | ||
}) | ||
|
||
it('should look like the subcall reverts with no data if value exceeds balance', async () => { | ||
const sendAmount = initialBalance0 + 1 | ||
const internalCalldata = ValueCalls1.interface.encodeFunctionData( | ||
'verifyCallValueAndReturn', | ||
[sendAmount] // this would be correct and return successfuly, IF it could get here | ||
) | ||
const [success, returndata] = await ValueCalls0.callStatic.sendWithData( | ||
ValueCalls1.address, | ||
sendAmount, | ||
internalCalldata | ||
) | ||
|
||
expect(success).to.be.false | ||
expect(returndata).to.eq('0x') | ||
}) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.