Commit 4c546a1f authored by Kelvin Fichter's avatar Kelvin Fichter Committed by GitHub

Integrates BondManager into master (#25)

* Upgraded to new RingBuffer

* First pass at verification function

* Removed BaseChain as a contract

* Update OVM_CanonicalTransactionChain.spec.ts

* Removed unused chain variable

* Added overwriting logic to CTC

* Corrected CTC event emit

* Remove timebound ring buffer tests

* Integrated bond manager PR
Co-authored-by: default avatarGeorgios Konstantopoulos <me@gakonst.com>
parent 43b3b3b0
......@@ -12,6 +12,8 @@ import { Lib_RingBuffer, iRingBufferOverwriter } from "../../libraries/utils/Lib
import { iOVM_FraudVerifier } from "../../iOVM/verification/iOVM_FraudVerifier.sol";
import { iOVM_StateCommitmentChain } from "../../iOVM/chain/iOVM_StateCommitmentChain.sol";
import { iOVM_CanonicalTransactionChain } from "../../iOVM/chain/iOVM_CanonicalTransactionChain.sol";
import { iOVM_BondManager } from "../../iOVM/verification/iOVM_BondManager.sol";
/**
* @title OVM_StateCommitmentChain
......@@ -36,7 +38,7 @@ contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, iRingBufferOverw
Lib_RingBuffer.RingBuffer internal batches;
iOVM_CanonicalTransactionChain internal ovmCanonicalTransactionChain;
iOVM_FraudVerifier internal ovmFraudVerifier;
iOVM_BondManager internal ovmBondManager;
/***************
* Constructor *
......@@ -52,6 +54,7 @@ contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, iRingBufferOverw
{
ovmCanonicalTransactionChain = iOVM_CanonicalTransactionChain(resolve("OVM_CanonicalTransactionChain"));
ovmFraudVerifier = iOVM_FraudVerifier(resolve("OVM_FraudVerifier"));
ovmBondManager = iOVM_BondManager(resolve("OVM_BondManager"));
batches.init(
16,
......@@ -69,7 +72,6 @@ contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, iRingBufferOverw
* @inheritdoc iOVM_StateCommitmentChain
*/
function getTotalElements()
virtual
override
public
view
......@@ -103,6 +105,12 @@ contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, iRingBufferOverw
override
public
{
// Proposers must have previously staked at the BondManager
require(
ovmBondManager.isCollateralized(msg.sender),
"Proposer does not have enough collateral posted"
);
require(
_batch.length > 0,
"Cannot submit an empty state batch."
......@@ -118,11 +126,11 @@ contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, iRingBufferOverw
elements[i] = abi.encodePacked(_batch[i]);
}
// Pass the block's timestamp and the publisher of the data
// to be used in the fraud proofs
_appendBatch(
elements,
abi.encode(
block.timestamp
)
abi.encode(block.timestamp, msg.sender)
);
}
......@@ -140,6 +148,11 @@ contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, iRingBufferOverw
"State batches can only be deleted by the OVM_FraudVerifier."
);
require(
Lib_OVMCodec.hashBatchHeader(_batchHeader) == batches.get(uint32(_batchHeader.batchIndex)),
"Invalid batch header."
);
require(
insideFraudProofWindow(_batchHeader),
"State batches can only be deleted within the fraud proof window."
......@@ -194,9 +207,9 @@ contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, iRingBufferOverw
bool _inside
)
{
uint256 timestamp = abi.decode(
(uint256 timestamp,) = abi.decode(
_batchHeader.extraData,
(uint256)
(uint256, address)
);
require(
......
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/* Library Imports */
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
/* Interface Imports */
import { iOVM_BondManager, Errors, ERC20 } from "../../iOVM/verification/iOVM_BondManager.sol";
import { iOVM_FraudVerifier } from "../../iOVM/verification/iOVM_FraudVerifier.sol";
/**
* @title OVM_BondManager
*/
contract OVM_BondManager is iOVM_BondManager, Lib_AddressResolver {
/****************************
* Constants and Parameters *
****************************/
/// The dispute period
uint256 public constant disputePeriodSeconds = 7 days;
/// The minimum collateral a sequencer must post
uint256 public requiredCollateral = 1 ether;
/// The maximum multiplier for updating the `requiredCollateral`
uint256 public constant MAX = 5;
/// Owner used to bump the security bond size
address immutable public owner;
/*******************************************
* Contract Variables: Contract References *
*******************************************/
/// The bond token
ERC20 immutable public token;
/// The fraud verifier contract, used to get data about transitioners for a pre-state root
address public ovmFraudVerifier;
/********************************************
* Contract Variables: Internal Accounting *
*******************************************/
/// The bonds posted by each proposer
mapping(address => Bond) public bonds;
/// For each pre-state root, there's an array of witnessProviders that must be rewarded
/// for posting witnesses
mapping(bytes32 => Rewards) public witnessProviders;
/***************
* Constructor *
***************/
/// Initializes with a ERC20 token to be used for the fidelity bonds
/// and with the Address Manager
constructor(ERC20 _token, address _libAddressManager)
Lib_AddressResolver(_libAddressManager)
{
owner = msg.sender;
token = _token;
ovmFraudVerifier = resolve("OVM_FraudVerifier");
}
/********************
* Public Functions *
********************/
/// Adds `who` to the list of witnessProviders for the provided `preStateRoot`.
function recordGasSpent(bytes32 _preStateRoot, address who, uint256 gasSpent) override public {
// The sender must be the transitioner that corresponds to the claimed pre-state root
address transitioner = address(iOVM_FraudVerifier(ovmFraudVerifier).getStateTransitioner(_preStateRoot));
require(transitioner == msg.sender, Errors.ONLY_TRANSITIONER);
witnessProviders[_preStateRoot].total += gasSpent;
witnessProviders[_preStateRoot].gasSpent[who] += gasSpent;
}
/// Slashes + distributes rewards or frees up the sequencer's bond, only called by
/// `FraudVerifier.finalizeFraudVerification`
function finalize(bytes32 _preStateRoot, uint256 batchIndex, address publisher, uint256 timestamp) override public {
require(msg.sender == ovmFraudVerifier, Errors.ONLY_FRAUD_VERIFIER);
require(witnessProviders[_preStateRoot].canClaim == false, Errors.ALREADY_FINALIZED);
// allow users to claim from that state root's
// pool of collateral (effectively slashing the sequencer)
witnessProviders[_preStateRoot].canClaim = true;
Bond storage bond = bonds[publisher];
// if the fraud proof's dispute period does not intersect with the
// withdrawal's timestamp, then the user should not be slashed
// e.g if a user at day 10 submits a withdrawal, and a fraud proof
// from day 1 gets published, the user won't be slashed since day 8 (1d + 7d)
// is before the user started their withdrawal. on the contrary, if the user
// had started their withdrawal at, say, day 6, they would be slashed
if (
bond.withdrawalTimestamp != 0 &&
uint256(bond.withdrawalTimestamp) > timestamp + disputePeriodSeconds &&
bond.state == State.WITHDRAWING
) {
return;
}
// slash!
bond.state = State.NOT_COLLATERALIZED;
}
/// Sequencers call this function to post collateral which will be used for
/// the `appendBatch` call
function deposit(uint256 amount) override public {
require(
token.transferFrom(msg.sender, address(this), amount),
Errors.ERC20_ERR
);
// This cannot overflow
bonds[msg.sender].state = State.COLLATERALIZED;
}
/// Starts the withdrawal for a publisher
function startWithdrawal() override public {
Bond storage bond = bonds[msg.sender];
require(bond.withdrawalTimestamp == 0, Errors.WITHDRAWAL_PENDING);
require(bond.state == State.COLLATERALIZED, Errors.WRONG_STATE);
bond.state = State.WITHDRAWING;
bond.withdrawalTimestamp = uint32(block.timestamp);
}
/// Finalizes a pending withdrawal from a publisher
function finalizeWithdrawal() override public {
Bond storage bond = bonds[msg.sender];
require(
block.timestamp >= uint256(bond.withdrawalTimestamp) + disputePeriodSeconds,
Errors.TOO_EARLY
);
require(bond.state == State.WITHDRAWING, Errors.SLASHED);
// refunds!
bond.state = State.NOT_COLLATERALIZED;
bond.withdrawalTimestamp = 0;
require(
token.transfer(msg.sender, requiredCollateral),
Errors.ERC20_ERR
);
}
/// Claims the user's reward for the witnesses they provided
function claim(bytes32 _preStateRoot) override public {
Rewards storage rewards = witnessProviders[_preStateRoot];
// only allow claiming if fraud was proven in `finalize`
require(rewards.canClaim, Errors.CANNOT_CLAIM);
// proportional allocation - only reward 50% (rest gets locked in the
// contract forever
uint256 amount = (requiredCollateral * rewards.gasSpent[msg.sender]) / (2 * rewards.total);
// reset the user's spent gas so they cannot double claim
rewards.gasSpent[msg.sender] = 0;
// transfer
require(token.transfer(msg.sender, amount), Errors.ERC20_ERR);
}
/// Sets the required collateral for posting a state root
/// Callable only by the contract's deployer.
function setRequiredCollateral(uint256 newValue) override public {
require(newValue > requiredCollateral, Errors.LOW_VALUE);
require(newValue < MAX * requiredCollateral, Errors.HIGH_VALUE);
require(msg.sender == owner, Errors.ONLY_OWNER);
requiredCollateral = newValue;
}
/// Checks if the user is collateralized for the batchIndex
function isCollateralized(address who) override public view returns (bool) {
return bonds[who].state == State.COLLATERALIZED;
}
/// Gets how many witnesses the user has provided for the state root
function getGasSpent(bytes32 preStateRoot, address who) override public view returns (uint256) {
return witnessProviders[preStateRoot].gasSpent[who];
}
}
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
import { iOVM_BondManager } from "../../iOVM/verification/iOVM_BondManager.sol";
/// Minimal contract to be inherited by contracts consumed by users that provide
/// data for fraud proofs
contract OVM_FraudContributor {
iOVM_BondManager internal ovmBondManager;
/// Decorate your functions with this modifier to store how much total gas was
/// consumed by the sender, to reward users fairly
modifier contributesToFraudProof(bytes32 preStateRoot) {
uint startGas = gasleft();
_;
uint gasSpent = startGas - gasleft();
ovmBondManager.recordGasSpent(preStateRoot, msg.sender, gasSpent);
}
}
......@@ -10,12 +10,16 @@ import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolve
import { iOVM_FraudVerifier } from "../../iOVM/verification/iOVM_FraudVerifier.sol";
import { iOVM_StateTransitioner } from "../../iOVM/verification/iOVM_StateTransitioner.sol";
import { iOVM_StateTransitionerFactory } from "../../iOVM/verification/iOVM_StateTransitionerFactory.sol";
import { iOVM_BondManager } from "../../iOVM/verification/iOVM_BondManager.sol";
import { iOVM_ExecutionManager } from "../../iOVM/execution/iOVM_ExecutionManager.sol";
import { iOVM_StateManagerFactory } from "../../iOVM/execution/iOVM_StateManagerFactory.sol";
import { iOVM_StateCommitmentChain } from "../../iOVM/chain/iOVM_StateCommitmentChain.sol";
import { iOVM_CanonicalTransactionChain } from "../../iOVM/chain/iOVM_CanonicalTransactionChain.sol";
contract OVM_FraudVerifier is iOVM_FraudVerifier, Lib_AddressResolver {
/* Contract Imports */
import { OVM_FraudContributor } from "./OVM_FraudContributor.sol";
contract OVM_FraudVerifier is OVM_FraudContributor, iOVM_FraudVerifier, Lib_AddressResolver {
/*******************************************
* Contract Variables: Contract References *
......@@ -46,6 +50,7 @@ contract OVM_FraudVerifier is iOVM_FraudVerifier, Lib_AddressResolver {
{
ovmStateCommitmentChain = iOVM_StateCommitmentChain(resolve("OVM_StateCommitmentChain"));
ovmCanonicalTransactionChain = iOVM_CanonicalTransactionChain(resolve("OVM_CanonicalTransactionChain"));
ovmBondManager = iOVM_BondManager(resolve("OVM_BondManager"));
}
......@@ -97,6 +102,7 @@ contract OVM_FraudVerifier is iOVM_FraudVerifier, Lib_AddressResolver {
)
override
public
contributesToFraudProof(_preStateRoot)
{
if (_hasStateTransitioner(_preStateRoot)) {
return;
......@@ -150,6 +156,7 @@ contract OVM_FraudVerifier is iOVM_FraudVerifier, Lib_AddressResolver {
)
override
public
contributesToFraudProof(_preStateRoot)
{
iOVM_StateTransitioner transitioner = transitioners[_preStateRoot];
......@@ -181,14 +188,27 @@ contract OVM_FraudVerifier is iOVM_FraudVerifier, Lib_AddressResolver {
"Invalid post-state root inclusion proof."
);
// If the post state root did not match, then there was fraud and we should delete the batch
require(
_postStateRoot != transitioner.getPostStateRoot(),
"State transition has not been proven fraudulent."
);
// delete the state batch
ovmStateCommitmentChain.deleteStateBatch(
_postStateRootBatchHeader
);
// Get the timestamp and publisher for that block
(uint256 timestamp, address publisher) = abi.decode(_postStateRootBatchHeader.extraData, (uint256, address));
// slash the bonds at the bond manager
ovmBondManager.finalize(
_preStateRoot,
_postStateRootBatchHeader.batchIndex,
publisher,
timestamp
);
}
......
......@@ -10,17 +10,21 @@ import { Lib_SecureMerkleTrie } from "../../libraries/trie/Lib_SecureMerkleTrie.
/* Interface Imports */
import { iOVM_StateTransitioner } from "../../iOVM/verification/iOVM_StateTransitioner.sol";
import { iOVM_BondManager } from "../../iOVM/verification/iOVM_BondManager.sol";
import { iOVM_ExecutionManager } from "../../iOVM/execution/iOVM_ExecutionManager.sol";
import { iOVM_StateManager } from "../../iOVM/execution/iOVM_StateManager.sol";
import { iOVM_StateManagerFactory } from "../../iOVM/execution/iOVM_StateManagerFactory.sol";
/* Contract Imports */
import { OVM_FraudContributor } from "./OVM_FraudContributor.sol";
/* Logging Imports */
import { console } from "@nomiclabs/buidler/console.sol";
/**
* @title OVM_StateTransitioner
*/
contract OVM_StateTransitioner is iOVM_StateTransitioner, Lib_AddressResolver {
contract OVM_StateTransitioner is OVM_FraudContributor, iOVM_StateTransitioner, Lib_AddressResolver {
/*******************
* Data Structures *
......@@ -77,6 +81,7 @@ contract OVM_StateTransitioner is iOVM_StateTransitioner, Lib_AddressResolver {
ovmExecutionManager = iOVM_ExecutionManager(resolve("OVM_ExecutionManager"));
ovmStateManager = iOVM_StateManagerFactory(resolve("OVM_StateManagerFactory")).create(address(this));
ovmBondManager = iOVM_BondManager(resolve("OVM_BondManager"));
}
......@@ -168,6 +173,7 @@ contract OVM_StateTransitioner is iOVM_StateTransitioner, Lib_AddressResolver {
override
public
onlyDuringPhase(TransitionPhase.PRE_EXECUTION)
contributesToFraudProof(preStateRoot)
{
// Exit quickly to avoid unnecessary work.
require(
......@@ -215,6 +221,7 @@ contract OVM_StateTransitioner is iOVM_StateTransitioner, Lib_AddressResolver {
override
public
onlyDuringPhase(TransitionPhase.PRE_EXECUTION)
contributesToFraudProof(preStateRoot)
{
// Exit quickly to avoid unnecessary work.
require(
......@@ -250,6 +257,7 @@ contract OVM_StateTransitioner is iOVM_StateTransitioner, Lib_AddressResolver {
override
public
onlyDuringPhase(TransitionPhase.PRE_EXECUTION)
contributesToFraudProof(preStateRoot)
{
// Exit quickly to avoid unnecessary work.
require(
......@@ -305,6 +313,7 @@ contract OVM_StateTransitioner is iOVM_StateTransitioner, Lib_AddressResolver {
override
public
onlyDuringPhase(TransitionPhase.PRE_EXECUTION)
contributesToFraudProof(preStateRoot)
{
require(
Lib_OVMCodec.hashTransaction(_transaction) == transactionHash,
......@@ -341,6 +350,7 @@ contract OVM_StateTransitioner is iOVM_StateTransitioner, Lib_AddressResolver {
override
public
onlyDuringPhase(TransitionPhase.POST_EXECUTION)
contributesToFraudProof(preStateRoot)
{
require(
ovmStateManager.commitAccount(_ovmContractAddress) == true,
......@@ -375,6 +385,7 @@ contract OVM_StateTransitioner is iOVM_StateTransitioner, Lib_AddressResolver {
override
public
onlyDuringPhase(TransitionPhase.POST_EXECUTION)
contributesToFraudProof(preStateRoot)
{
require(
ovmStateManager.commitContractStorage(_ovmContractAddress, _key) == true,
......
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
interface ERC20 {
function transfer(address, uint256) external returns (bool);
function transferFrom(address, address, uint256) external returns (bool);
}
/// All the errors which may be encountered on the bond manager
library Errors {
string constant ERC20_ERR = "BondManager: Could not post bond";
string constant LOW_VALUE = "BondManager: New collateral value must be greater than the previous one";
string constant HIGH_VALUE = "BondManager: New collateral value cannot be more than 5x of the previous one";
string constant ALREADY_FINALIZED = "BondManager: Fraud proof for this pre-state root has already been finalized";
string constant SLASHED = "BondManager: Cannot finalize withdrawal, you probably got slashed";
string constant WRONG_STATE = "BondManager: Wrong bond state for proposer";
string constant CANNOT_CLAIM = "BondManager: Cannot claim yet. Dispute must be finalized first";
string constant WITHDRAWAL_PENDING = "BondManager: Withdrawal already pending";
string constant TOO_EARLY = "BondManager: Too early to finalize your withdrawal";
string constant ONLY_OWNER = "BondManager: Only the contract's owner can call this function";
string constant ONLY_TRANSITIONER = "BondManager: Only the transitioner for this pre-state root may call this function";
string constant ONLY_FRAUD_VERIFIER = "BondManager: Only the fraud verifier may call this function";
string constant ONLY_STATE_COMMITMENT_CHAIN = "BondManager: Only the state commitment chain may call this function";
}
/**
* @title iOVM_BondManager
*/
interface iOVM_BondManager {
/*******************
* Data Structures *
*******************/
/// The lifecycle of a proposer's bond
enum State {
// Before depositing or after getting slashed, a user is uncollateralized
NOT_COLLATERALIZED,
// After depositing, a user is collateralized
COLLATERALIZED,
// After a user has initiated a withdrawal
WITHDRAWING
}
/// A bond posted by a proposer
struct Bond {
// The user's state
State state;
// The timestamp at which a proposer issued their withdrawal request
uint32 withdrawalTimestamp;
}
// Per pre-state root, store the number of state provisions that were made
// and how many of these calls were made by each user. Payouts will then be
// claimed by users proportionally for that dispute.
struct Rewards {
// Flag to check if rewards for a fraud proof are claimable
bool canClaim;
// Total number of `recordGasSpent` calls made
uint256 total;
// The gas spent by each user to provide witness data. The sum of all
// values inside this map MUST be equal to the value of `total`
mapping(address => uint256) gasSpent;
}
/********************
* Public Functions *
********************/
function recordGasSpent(
bytes32 _preStateRoot,
address _who,
uint256 _gasSpent
) external;
function finalize(
bytes32 _preStateRoot,
uint256 _batchIndex,
address _publisher,
uint256 _timestamp
) external;
function deposit(
uint256 _amount
) external;
function startWithdrawal() external;
function finalizeWithdrawal() external;
function claim(
bytes32 _preStateRoot
) external;
function setRequiredCollateral(
uint256 _newValue
) external;
function isCollateralized(
address _who
) external view returns (bool);
function getGasSpent(
bytes32 _preStateRoot,
address _who
) external view returns (uint256);
}
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
import { OVM_BondManager } from "./../optimistic-ethereum/OVM/verification/OVM_BondManager.sol";
contract Mock_FraudVerifier {
OVM_BondManager bondManager;
mapping (bytes32 => address) transitioners;
function setBondManager(OVM_BondManager _bondManager) public {
bondManager = _bondManager;
}
function setStateTransitioner(bytes32 preStateRoot, address addr) public {
transitioners[preStateRoot] = addr;
}
function getStateTransitioner(bytes32 preStateRoot) public view returns (address) {
return transitioners[preStateRoot];
}
function finalize(bytes32 _preStateRoot, uint256 batchIndex, address publisher, uint256 timestamp) public {
bondManager.finalize(_preStateRoot, batchIndex, publisher, timestamp);
}
}
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
// a test ERC20 token with an open mint function
contract TestERC20 {
using SafeMath for uint;
string public constant name = 'Test';
string public constant symbol = 'TST';
uint8 public constant decimals = 18;
uint public totalSupply;
mapping(address => uint) public balanceOf;
mapping(address => mapping(address => uint)) public allowance;
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
constructor() public {}
function mint(address to, uint value) public {
totalSupply = totalSupply.add(value);
balanceOf[to] = balanceOf[to].add(value);
emit Transfer(address(0), to, value);
}
function _approve(address owner, address spender, uint value) private {
allowance[owner][spender] = value;
emit Approval(owner, spender, value);
}
function _transfer(address from, address to, uint value) private {
balanceOf[from] = balanceOf[from].sub(value);
balanceOf[to] = balanceOf[to].add(value);
emit Transfer(from, to, value);
}
function approve(address spender, uint value) external returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
function transfer(address to, uint value) external returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
function transferFrom(address from, address to, uint value) external returns (bool) {
if (allowance[from][msg.sender] != uint(-1)) {
allowance[from][msg.sender] = allowance[from][msg.sender].sub(value);
}
_transfer(from, to, value);
return true;
}
}
library SafeMath {
function add(uint x, uint y) internal pure returns (uint z) {
require((z = x + y) >= x, 'ds-math-add-overflow');
}
function sub(uint x, uint y) internal pure returns (uint z) {
require((z = x - y) <= x, 'ds-math-sub-underflow');
}
function mul(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
}
}
This diff is collapsed.
......@@ -29,6 +29,7 @@ describe('OVM_StateCommitmentChain', () => {
})
let Mock__OVM_CanonicalTransactionChain: MockContract
let Mock__OVM_BondManager: MockContract
before(async () => {
Mock__OVM_CanonicalTransactionChain = smockit(
await ethers.getContractFactory('OVM_CanonicalTransactionChain')
......@@ -39,6 +40,18 @@ describe('OVM_StateCommitmentChain', () => {
'OVM_CanonicalTransactionChain',
Mock__OVM_CanonicalTransactionChain
)
Mock__OVM_BondManager = smockit(
await ethers.getContractFactory('OVM_BondManager')
)
await setProxyTarget(
AddressManager,
'OVM_BondManager',
Mock__OVM_BondManager
)
Mock__OVM_BondManager.smocked.isCollateralized.will.return.with(true)
})
let Factory__OVM_StateCommitmentChain: ContractFactory
......@@ -116,8 +129,8 @@ describe('OVM_StateCommitmentChain', () => {
)
await OVM_StateCommitmentChain.appendStateBatch(batch)
batchHeader.extraData = defaultAbiCoder.encode(
['uint256'],
[await getEthTime(ethers.provider)]
['uint256', 'address'],
[await getEthTime(ethers.provider), await signer.getAddress()]
)
})
......@@ -150,7 +163,7 @@ describe('OVM_StateCommitmentChain', () => {
...batchHeader,
batchIndex: 1,
})
).to.be.revertedWith('Invalid batch index.')
).to.be.revertedWith('Index out of bounds.')
})
})
......
......@@ -36,6 +36,7 @@ describe('OVM_FraudVerifier', () => {
let Mock__OVM_CanonicalTransactionChain: MockContract
let Mock__OVM_StateTransitioner: MockContract
let Mock__OVM_StateTransitionerFactory: MockContract
let Mock__OVM_BondManager: MockContract
before(async () => {
Mock__OVM_StateCommitmentChain = smockit(
await ethers.getContractFactory('OVM_StateCommitmentChain')
......@@ -52,6 +53,9 @@ describe('OVM_FraudVerifier', () => {
Mock__OVM_StateTransitionerFactory = smockit(
await ethers.getContractFactory('OVM_StateTransitionerFactory')
)
Mock__OVM_BondManager = smockit(
await ethers.getContractFactory('OVM_BondManager')
)
await setProxyTarget(
AddressManager,
......@@ -71,6 +75,12 @@ describe('OVM_FraudVerifier', () => {
Mock__OVM_StateTransitionerFactory
)
await setProxyTarget(
AddressManager,
'OVM_BondManager',
Mock__OVM_BondManager
)
Mock__OVM_StateTransitionerFactory.smocked.create.will.return.with(
Mock__OVM_StateTransitioner.address
)
......
......@@ -33,6 +33,7 @@ describe('OVM_StateTransitioner', () => {
let Mock__OVM_ExecutionManager: MockContract
let Mock__OVM_StateManagerFactory: MockContract
let Mock__OVM_StateManager: MockContract
let Mock__OVM_BondManager: MockContract
before(async () => {
Mock__OVM_ExecutionManager = smockit(
await ethers.getContractFactory('OVM_ExecutionManager')
......@@ -43,6 +44,16 @@ describe('OVM_StateTransitioner', () => {
Mock__OVM_StateManager = smockit(
await ethers.getContractFactory('OVM_StateManager')
)
Mock__OVM_BondManager = smockit(
await ethers.getContractFactory('OVM_BondManager')
)
await setProxyTarget(
AddressManager,
'OVM_BondManager',
Mock__OVM_BondManager
)
Mock__OVM_BondManager.smocked.recordGasSpent.will.return()
await setProxyTarget(
AddressManager,
......
import { NULL_BYTES32 } from '../constants'
import { NULL_BYTES32, NON_ZERO_ADDRESS } from '../constants'
import { ethers } from '@nomiclabs/buidler'
export const DUMMY_BATCH_HEADERS = [
{
......@@ -6,7 +7,10 @@ export const DUMMY_BATCH_HEADERS = [
batchRoot: NULL_BYTES32,
batchSize: 0,
prevTotalElements: 0,
extraData: NULL_BYTES32,
extraData: ethers.utils.defaultAbiCoder.encode(
['uint256', 'address'],
[NULL_BYTES32, NON_ZERO_ADDRESS]
),
},
]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment