Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
6e1dbfe0
Commit
6e1dbfe0
authored
Sep 28, 2020
by
Kelvin Fichter
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Transition to use address resolver pattern
parent
fb3c1643
Changes
87
Hide whitespace changes
Inline
Side-by-side
Showing
87 changed files
with
9454 additions
and
63 deletions
+9454
-63
buidler.config.d.ts
packages/contracts/build/buidler.config.d.ts
+4
-0
buidler.config.js
packages/contracts/build/buidler.config.js
+24
-0
buidler.config.js.map
packages/contracts/build/buidler.config.js.map
+1
-0
OVM_ECDSAContractAccount.sol
...build/contracts/OVM/accounts/OVM_ECDSAContractAccount.sol
+89
-0
OVM_BaseCrossDomainMessenger.sol
...ild/contracts/OVM/bridge/OVM_BaseCrossDomainMessenger.sol
+77
-0
OVM_L1CrossDomainMessenger.sol
...build/contracts/OVM/bridge/OVM_L1CrossDomainMessenger.sol
+251
-0
OVM_L2CrossDomainMessenger.sol
...build/contracts/OVM/bridge/OVM_L2CrossDomainMessenger.sol
+149
-0
OVM_BaseChain.sol
...ges/contracts/build/contracts/OVM/chain/OVM_BaseChain.sol
+208
-0
OVM_CanonicalTransactionChain.sol
...ild/contracts/OVM/chain/OVM_CanonicalTransactionChain.sol
+155
-0
OVM_StateCommitmentChain.sol
...ts/build/contracts/OVM/chain/OVM_StateCommitmentChain.sol
+96
-0
OVM_ExecutionManager.sol
...ts/build/contracts/OVM/execution/OVM_ExecutionManager.sol
+1688
-0
OVM_SafetyChecker.sol
...racts/build/contracts/OVM/execution/OVM_SafetyChecker.sol
+33
-0
OVM_StateManager.sol
...tracts/build/contracts/OVM/execution/OVM_StateManager.sol
+563
-0
OVM_StateManagerFactory.sol
...build/contracts/OVM/execution/OVM_StateManagerFactory.sol
+36
-0
OVM_DeployerWhitelist.sol
...build/contracts/OVM/precompiles/OVM_DeployerWhitelist.sol
+200
-0
OVM_L1MessageSender.sol
...s/build/contracts/OVM/precompiles/OVM_L1MessageSender.sol
+29
-0
OVM_L2ToL1MessagePasser.sol
...ild/contracts/OVM/precompiles/OVM_L2ToL1MessagePasser.sol
+44
-0
OVM_BaseQueue.sol
...ges/contracts/build/contracts/OVM/queue/OVM_BaseQueue.sol
+108
-0
OVM_L1ToL2TransactionQueue.sol
.../build/contracts/OVM/queue/OVM_L1ToL2TransactionQueue.sol
+88
-0
OVM_FraudVerifier.sol
...ts/build/contracts/OVM/verification/OVM_FraudVerifier.sol
+262
-0
OVM_StateTransitioner.sol
...uild/contracts/OVM/verification/OVM_StateTransitioner.sol
+352
-0
OVM_StateTransitionerFactory.sol
...ntracts/OVM/verification/OVM_StateTransitionerFactory.sol
+47
-0
iOVM_ECDSAContractAccount.sol
...ild/contracts/iOVM/accounts/iOVM_ECDSAContractAccount.sol
+24
-0
iOVM_BaseCrossDomainMessenger.sol
...d/contracts/iOVM/bridge/iOVM_BaseCrossDomainMessenger.sol
+21
-0
iOVM_L1CrossDomainMessenger.sol
...ild/contracts/iOVM/bridge/iOVM_L1CrossDomainMessenger.sol
+76
-0
iOVM_L2CrossDomainMessenger.sol
...ild/contracts/iOVM/bridge/iOVM_L2CrossDomainMessenger.sol
+42
-0
iOVM_BaseChain.sol
...s/contracts/build/contracts/iOVM/chain/iOVM_BaseChain.sol
+30
-0
iOVM_CanonicalTransactionChain.sol
...d/contracts/iOVM/chain/iOVM_CanonicalTransactionChain.sol
+19
-0
iOVM_StateCommitmentChain.sol
.../build/contracts/iOVM/chain/iOVM_StateCommitmentChain.sol
+22
-0
iOVM_ExecutionManager.sol
.../build/contracts/iOVM/execution/iOVM_ExecutionManager.sol
+159
-0
iOVM_SafetyChecker.sol
...cts/build/contracts/iOVM/execution/iOVM_SafetyChecker.sol
+14
-0
iOVM_StateManager.sol
...acts/build/contracts/iOVM/execution/iOVM_StateManager.sol
+64
-0
iOVM_StateManagerFactory.sol
...ild/contracts/iOVM/execution/iOVM_StateManagerFactory.sol
+23
-0
iOVM_DeployerWhitelist.sol
...ild/contracts/iOVM/precompiles/iOVM_DeployerWhitelist.sol
+19
-0
iOVM_L1MessageSender.sol
...build/contracts/iOVM/precompiles/iOVM_L1MessageSender.sol
+14
-0
iOVM_L2ToL1MessagePasser.sol
...d/contracts/iOVM/precompiles/iOVM_L2ToL1MessagePasser.sol
+25
-0
iOVM_BaseQueue.sol
...s/contracts/build/contracts/iOVM/queue/iOVM_BaseQueue.sol
+19
-0
iOVM_L1ToL2TransactionQueue.sol
...uild/contracts/iOVM/queue/iOVM_L1ToL2TransactionQueue.sol
+22
-0
iOVM_FraudVerifier.sol
.../build/contracts/iOVM/verification/iOVM_FraudVerifier.sol
+44
-0
iOVM_StateTransitioner.sol
...ld/contracts/iOVM/verification/iOVM_StateTransitioner.sol
+74
-0
iOVM_StateTransitionerFactory.sol
...racts/iOVM/verification/iOVM_StateTransitionerFactory.sol
+26
-0
Lib_OVMCodec.sol
...ontracts/build/contracts/libraries/codec/Lib_OVMCodec.sol
+161
-0
Lib_AddressManager.sol
...build/contracts/libraries/resolver/Lib_AddressManager.sol
+55
-0
Lib_AddressResolver.sol
...uild/contracts/libraries/resolver/Lib_AddressResolver.sol
+50
-0
Lib_RLPReader.sol
...contracts/build/contracts/libraries/rlp/Lib_RLPReader.sol
+372
-0
Lib_RLPWriter.sol
...contracts/build/contracts/libraries/rlp/Lib_RLPWriter.sol
+340
-0
Lib_EthMerkleTrie.sol
...acts/build/contracts/libraries/trie/Lib_EthMerkleTrie.sol
+781
-0
Lib_MerkleTrie.sol
...ntracts/build/contracts/libraries/trie/Lib_MerkleTrie.sol
+984
-0
Lib_SecureMerkleTrie.sol
...s/build/contracts/libraries/trie/Lib_SecureMerkleTrie.sol
+159
-0
Lib_ByteUtils.sol
...ntracts/build/contracts/libraries/utils/Lib_ByteUtils.sol
+238
-0
Lib_Bytes32Utils.sol
...acts/build/contracts/libraries/utils/Lib_Bytes32Utils.sol
+60
-0
Lib_ECDSAUtils.sol
...tracts/build/contracts/libraries/utils/Lib_ECDSAUtils.sol
+92
-0
Lib_EthUtils.sol
...ontracts/build/contracts/libraries/utils/Lib_EthUtils.sol
+210
-0
Lib_MerkleUtils.sol
...racts/build/contracts/libraries/utils/Lib_MerkleUtils.sol
+137
-0
mockOVM_CrossDomainMessenger.sol
...contracts/mockOVM/bridge/mockOVM_CrossDomainMessenger.sol
+130
-0
Proxy_Forwarder.sol
packages/contracts/build/contracts/proxy/Proxy_Forwarder.sol
+0
-0
Proxy_Manager.sol
packages/contracts/build/contracts/proxy/Proxy_Manager.sol
+0
-0
Proxy_Resolver.sol
packages/contracts/build/contracts/proxy/Proxy_Resolver.sol
+0
-0
modify-compiler.d.ts
...contracts/build/test/helpers/buidler/modify-compiler.d.ts
+1
-0
modify-compiler.js
...s/contracts/build/test/helpers/buidler/modify-compiler.js
+43
-0
modify-compiler.js.map
...ntracts/build/test/helpers/buidler/modify-compiler.js.map
+1
-0
constants.d.ts
packages/contracts/build/test/helpers/constants.d.ts
+26
-0
constants.js
packages/contracts/build/test/helpers/constants.js
+38
-0
constants.js.map
packages/contracts/build/test/helpers/constants.js.map
+1
-0
buffer-utils.d.ts
...ages/contracts/build/test/helpers/utils/buffer-utils.d.ts
+3
-0
buffer-utils.js
packages/contracts/build/test/helpers/utils/buffer-utils.js
+13
-0
buffer-utils.js.map
...es/contracts/build/test/helpers/utils/buffer-utils.js.map
+1
-0
byte-utils.d.ts
packages/contracts/build/test/helpers/utils/byte-utils.d.ts
+3
-0
byte-utils.js
packages/contracts/build/test/helpers/utils/byte-utils.js
+18
-0
byte-utils.js.map
...ages/contracts/build/test/helpers/utils/byte-utils.js.map
+1
-0
index.d.ts
packages/contracts/build/test/helpers/utils/index.d.ts
+2
-0
index.js
packages/contracts/build/test/helpers/utils/index.js
+15
-0
index.js.map
packages/contracts/build/test/helpers/utils/index.js.map
+1
-0
OVM_L1CrossDomainMessenger.sol
...mistic-ethereum/OVM/bridge/OVM_L1CrossDomainMessenger.sol
+5
-7
OVM_L2CrossDomainMessenger.sol
...mistic-ethereum/OVM/bridge/OVM_L2CrossDomainMessenger.sol
+6
-6
OVM_CanonicalTransactionChain.sol
...stic-ethereum/OVM/chain/OVM_CanonicalTransactionChain.sol
+5
-7
OVM_StateCommitmentChain.sol
...ptimistic-ethereum/OVM/chain/OVM_StateCommitmentChain.sol
+5
-7
OVM_L1ToL2TransactionQueue.sol
...imistic-ethereum/OVM/queue/OVM_L1ToL2TransactionQueue.sol
+5
-7
OVM_FraudVerifier.sol
...ptimistic-ethereum/OVM/verification/OVM_FraudVerifier.sol
+6
-8
OVM_StateTransitioner.sol
...istic-ethereum/OVM/verification/OVM_StateTransitioner.sol
+6
-8
OVM_StateTransitionerFactory.sol
...thereum/OVM/verification/OVM_StateTransitionerFactory.sol
+3
-3
Lib_AddressManager.sol
...mistic-ethereum/libraries/resolver/Lib_AddressManager.sol
+55
-0
Lib_AddressResolver.sol
...istic-ethereum/libraries/resolver/Lib_AddressResolver.sol
+50
-0
package.json
packages/contracts/package.json
+6
-2
constants.ts
packages/contracts/test/helpers/constants.ts
+1
-0
tsconfig.json
packages/contracts/tsconfig.json
+1
-1
yarn.lock
packages/contracts/yarn.lock
+123
-7
No files found.
packages/contracts/build/buidler.config.d.ts
0 → 100644
View file @
6e1dbfe0
import
{
BuidlerConfig
}
from
'
@nomiclabs/buidler/config
'
;
import
'
./test/helpers/buidler/modify-compiler
'
;
declare
const
config
:
BuidlerConfig
;
export
default
config
;
packages/contracts/build/buidler.config.js
0 → 100644
View file @
6e1dbfe0
"
use strict
"
;
Object
.
defineProperty
(
exports
,
"
__esModule
"
,
{
value
:
true
});
const
config_1
=
require
(
"
@nomiclabs/buidler/config
"
);
const
constants_1
=
require
(
"
./test/helpers/constants
"
);
config_1
.
usePlugin
(
'
@nomiclabs/buidler-ethers
'
);
config_1
.
usePlugin
(
'
@nomiclabs/buidler-waffle
'
);
require
(
"
./test/helpers/buidler/modify-compiler
"
);
const
config
=
{
networks
:
{
buidlerevm
:
{
accounts
:
constants_1
.
DEFAULT_ACCOUNTS_BUIDLER
,
blockGasLimit
:
constants_1
.
RUN_OVM_TEST_GAS
*
2
,
},
},
mocha
:
{
timeout
:
50000
,
},
solc
:
{
version
:
'
0.7.0
'
,
optimizer
:
{
enabled
:
true
,
runs
:
200
},
},
};
exports
.
default
=
config
;
//# sourceMappingURL=buidler.config.js.map
\ No newline at end of file
packages/contracts/build/buidler.config.js.map
0 → 100644
View file @
6e1dbfe0
{"version":3,"file":"buidler.config.js","sourceRoot":"","sources":["../buidler.config.ts"],"names":[],"mappings":";;AAAA,sDAAoE;AAEpE,wDAGiC;AAEjC,kBAAS,CAAC,2BAA2B,CAAC,CAAA;AACtC,kBAAS,CAAC,2BAA2B,CAAC,CAAA;AAEtC,kDAA+C;AAE/C,MAAM,MAAM,GAAkB;IAC5B,QAAQ,EAAE;QACR,UAAU,EAAE;YACV,QAAQ,EAAE,oCAAwB;YAClC,aAAa,EAAE,4BAAgB,GAAG,CAAC;SACpC;KACF;IACD,KAAK,EAAE;QACL,OAAO,EAAE,KAAK;KACf;IACD,IAAI,EAAE;QACJ,OAAO,EAAE,OAAO;QAChB,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE;KACxC;CACF,CAAA;AAED,kBAAe,MAAM,CAAA"}
\ No newline at end of file
packages/contracts/build/contracts/OVM/accounts/OVM_ECDSAContractAccount.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Interface Imports */
import { iOVM_ECDSAContractAccount } from "../../iOVM/accounts/iOVM_ECDSAContractAccount.sol";
import { iOVM_ExecutionManager } from "../../iOVM/execution/iOVM_ExecutionManager.sol";
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_ECDSAUtils } from "../../libraries/utils/Lib_ECDSAUtils.sol";
/**
* @title OVM_ECDSAContractAccount
*/
contract OVM_ECDSAContractAccount is iOVM_ECDSAContractAccount {
/********************
* Public Functions *
********************/
/**
* Executes a signed transaction.
* @param _transaction Signed EOA transaction.
* @param _signatureType Hashing scheme used for the transaction (e.g., ETH signed message).
* @param _v Signature `v` parameter.
* @param _r Signature `r` parameter.
* @param _s Signature `s` parameter.
* @return _success Whether or not the call returned (rather than reverted).
* @return _returndata Data returned by the call.
*/
function execute(
bytes memory _transaction,
Lib_OVMCodec.EOASignatureType _signatureType,
uint8 _v,
bytes32 _r,
bytes32 _s
)
override
public
returns (
bool _success,
bytes memory _returndata
)
{
iOVM_ExecutionManager ovmExecutionManager = iOVM_ExecutionManager(msg.sender);
// Address of this contract within the ovm (ovmADDRESS) should be the same as the
// recovered address of the user who signed this message. This is how we manage to shim
// account abstraction even though the user isn't a contract.
require(
Lib_ECDSAUtils.recover(
_transaction,
_signatureType == Lib_OVMCodec.EOASignatureType.ETH_SIGNED_MESSAGE,
_v,
_r,
_s,
ovmExecutionManager.ovmCHAINID()
) == ovmExecutionManager.ovmADDRESS(),
"Signature provided for EOA transaction execution is invalid."
);
Lib_OVMCodec.EOATransaction memory decodedTx = Lib_OVMCodec.decodeEOATransaction(_transaction);
// Need to make sure that the transaction nonce is right and bump it if so.
require(
decodedTx.nonce == ovmExecutionManager.ovmGETNONCE() + 1,
"Transaction nonce does not match the expected nonce."
);
ovmExecutionManager.ovmSETNONCE(decodedTx.nonce);
// Contract creations are signalled by sending a transaction to the zero address.
if (decodedTx.target == address(0)) {
address created = ovmExecutionManager.ovmCREATE{gas: decodedTx.gasLimit}(
decodedTx.data
);
// EVM doesn't tell us whether a contract creation failed, even if it reverted during
// initialization. Always return `true` for our success value here.
return (true, abi.encode(created));
} else {
return ovmExecutionManager.ovmCALL(
decodedTx.gasLimit,
decodedTx.target,
decodedTx.data
);
}
}
}
packages/contracts/build/contracts/OVM/bridge/OVM_BaseCrossDomainMessenger.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Interface Imports */
import { iOVM_BaseCrossDomainMessenger } from "../../iOVM/bridge/iOVM_BaseCrossDomainMessenger.sol";
/**
* @title OVM_BaseCrossDomainMessenger
*/
contract OVM_BaseCrossDomainMessenger is iOVM_BaseCrossDomainMessenger {
/**********************
* Contract Variables *
**********************/
mapping (bytes32 => bool) public receivedMessages;
mapping (bytes32 => bool) public sentMessages;
address public targetMessengerAddress;
uint256 public messageNonce;
address public xDomainMessageSender;
/********************
* Public Functions *
********************/
/**
* Sets the target messenger address.
* @dev Currently, this function is public and therefore allows anyone to modify the target
* messenger for a given xdomain messenger contract. Obviously this shouldn't be allowed,
* but we still need to determine an adequate mechanism for updating this address.
* @param _targetMessengerAddress New messenger address.
*/
function setTargetMessengerAddress(
address _targetMessengerAddress
)
override
public
{
targetMessengerAddress = _targetMessengerAddress;
}
/**********************
* Internal Functions *
**********************/
/**
* Generates the correct cross domain calldata for a message.
* @param _target Target contract address.
* @param _sender Message sender address.
* @param _message Message to send to the target.
* @param _messageNonce Nonce for the provided message.
* @return ABI encoded cross domain calldata.
*/
function _getXDomainCalldata(
address _target,
address _sender,
bytes memory _message,
uint256 _messageNonce
)
internal
pure
returns (
bytes memory
)
{
return abi.encodeWithSelector(
bytes4(keccak256(bytes("relayMessage(address,address,bytes,uint256)"))),
_target,
_sender,
_message,
_messageNonce
);
}
}
packages/contracts/build/contracts/OVM/bridge/OVM_L1CrossDomainMessenger.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
import { Lib_EthMerkleTrie } from "../../libraries/trie/Lib_EthMerkleTrie.sol";
import { Lib_ByteUtils } from "../../libraries/utils/Lib_ByteUtils.sol";
/* Interface Imports */
import { iOVM_L1CrossDomainMessenger } from "../../iOVM/bridge/iOVM_L1CrossDomainMessenger.sol";
import { iOVM_L1ToL2TransactionQueue } from "../../iOVM/queue/iOVM_L1ToL2TransactionQueue.sol";
import { iOVM_StateCommitmentChain } from "../../iOVM/chain/iOVM_StateCommitmentChain.sol";
/* Contract Imports */
import { OVM_BaseCrossDomainMessenger } from "./OVM_BaseCrossDomainMessenger.sol";
/**
* @title OVM_L1CrossDomainMessenger
*/
contract OVM_L1CrossDomainMessenger is iOVM_L1CrossDomainMessenger, OVM_BaseCrossDomainMessenger, Lib_AddressResolver {
/*******************************************
* Contract Variables: Contract References *
*******************************************/
iOVM_L1ToL2TransactionQueue internal ovmL1ToL2TransactionQueue;
iOVM_StateCommitmentChain internal ovmStateCommitmentChain;
/***************
* Constructor *
***************/
/**
* @param _libAddressManager Address of the Address Manager.
*/
constructor(
address _libAddressManager
)
Lib_AddressResolver(_libAddressManager)
{
ovmL1ToL2TransactionQueue = iOVM_L1ToL2TransactionQueue(resolve("OVM_L1ToL2TransactionQueue"));
ovmStateCommitmentChain = iOVM_StateCommitmentChain(resolve("OVM_StateCommitmentChain"));
}
/********************
* Public Functions *
********************/
/**
* Relays a cross domain message to a contract.
* @inheritdoc iOVM_L1CrossDomainMessenger
*/
function relayMessage(
address _target,
address _sender,
bytes memory _message,
uint256 _messageNonce,
L2MessageInclusionProof memory _proof
)
override
public
{
bytes memory xDomainCalldata = _getXDomainCalldata(
_target,
_sender,
_message,
_messageNonce
);
require(
_verifyXDomainMessage(
xDomainCalldata,
_proof
) == true,
"Provided message could not be verified."
);
require(
receivedMessages[keccak256(xDomainCalldata)] == false,
"Provided message has already been received."
);
xDomainMessageSender = _sender;
_target.call(_message);
// Messages are considered successfully executed if they complete
// without running out of gas (revert or not). As a result, we can
// ignore the result of the call and always mark the message as
// successfully executed because we won't get here unless we have
// enough gas left over.
receivedMessages[keccak256(xDomainCalldata)] = true;
}
/**
* Sends a cross domain message to the target messenger.
* @inheritdoc iOVM_L1CrossDomainMessenger
*/
function sendMessage(
address _target,
bytes memory _message,
uint32 _gasLimit
)
override
public
{
bytes memory xDomainCalldata = _getXDomainCalldata(
_target,
msg.sender,
_message,
messageNonce
);
_sendXDomainMessage(xDomainCalldata, _gasLimit);
messageNonce += 1;
sentMessages[keccak256(xDomainCalldata)] = true;
}
/**
* Replays a cross domain message to the target messenger.
* @inheritdoc iOVM_L1CrossDomainMessenger
*/
function replayMessage(
address _target,
address _sender,
bytes memory _message,
uint256 _messageNonce,
uint32 _gasLimit
)
override
public
{
bytes memory xDomainCalldata = _getXDomainCalldata(
_target,
_sender,
_message,
_messageNonce
);
require(
sentMessages[keccak256(xDomainCalldata)] == true,
"Provided message has not already been sent."
);
_sendXDomainMessage(xDomainCalldata, _gasLimit);
}
/**********************
* Internal Functions *
**********************/
/**
* Verifies that the given message is valid.
* @param _xDomainCalldata Calldata to verify.
* @param _proof Inclusion proof for the message.
* @return Whether or not the provided message is valid.
*/
function _verifyXDomainMessage(
bytes memory _xDomainCalldata,
L2MessageInclusionProof memory _proof
)
internal
returns (
bool
)
{
return (
_verifyStateRootProof(_proof)
&& _verifyStorageProof(_xDomainCalldata, _proof)
);
}
/**
* Verifies that the state root within an inclusion proof is valid.
* @param _proof Message inclusion proof.
* @return Whether or not the provided proof is valid.
*/
function _verifyStateRootProof(
L2MessageInclusionProof memory _proof
)
internal
returns (
bool
)
{
// TODO: We *must* verify that the batch timestamp is sufficiently old.
// However, this requires that we first add timestamps to state batches
// and account for that change in various tests. Change of that size is
// out of scope for this ticket, so "TODO" for now.
return ovmStateCommitmentChain.verifyElement(
abi.encodePacked(_proof.stateRoot),
_proof.stateRootBatchHeader,
_proof.stateRootProof
);
}
/**
* Verifies that the storage proof within an inclusion proof is valid.
* @param _xDomainCalldata Encoded message calldata.
* @param _proof Message inclusion proof.
* @return Whether or not the provided proof is valid.
*/
function _verifyStorageProof(
bytes memory _xDomainCalldata,
L2MessageInclusionProof memory _proof
)
internal
returns (
bool
)
{
bytes32 storageKey = keccak256(
Lib_ByteUtils.concat(
abi.encodePacked(keccak256(_xDomainCalldata)),
abi.encodePacked(uint256(0))
)
);
return Lib_EthMerkleTrie.proveAccountStorageSlotValue(
0x4200000000000000000000000000000000000000,
storageKey,
bytes32(uint256(1)),
_proof.stateTrieWitness,
_proof.storageTrieWitness,
_proof.stateRoot
);
}
/**
* Sends a cross domain message.
* @param _message Message to send.
* @param _gasLimit OVM gas limit for the message.
*/
function _sendXDomainMessage(
bytes memory _message,
uint32 _gasLimit
)
internal
{
ovmL1ToL2TransactionQueue.enqueue(
targetMessengerAddress,
_gasLimit,
_message
);
}
}
packages/contracts/build/contracts/OVM/bridge/OVM_L2CrossDomainMessenger.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
/* Interface Imports */
import { iOVM_L2CrossDomainMessenger } from "../../iOVM/bridge/iOVM_L2CrossDomainMessenger.sol";
import { iOVM_L1MessageSender } from "../../iOVM/precompiles/iOVM_L1MessageSender.sol";
import { iOVM_L2ToL1MessagePasser } from "../../iOVM/precompiles/iOVM_L2ToL1MessagePasser.sol";
/* Contract Imports */
import { OVM_BaseCrossDomainMessenger } from "./OVM_BaseCrossDomainMessenger.sol";
/**
* @title OVM_L2CrossDomainMessenger
*/
contract OVM_L2CrossDomainMessenger is iOVM_L2CrossDomainMessenger, OVM_BaseCrossDomainMessenger, Lib_AddressResolver {
/*******************************************
* Contract Variables: Contract References *
*******************************************/
iOVM_L1MessageSender internal ovmL1MessageSender;
iOVM_L2ToL1MessagePasser internal ovmL2ToL1MessagePasser;
/***************
* Constructor *
***************/
/**
* @param _libAddressManager Address of the Address Manager.
*/
constructor(
address _libAddressManager
)
Lib_AddressResolver(_libAddressManager)
{
ovmL1MessageSender = iOVM_L1MessageSender(resolve("OVM_L1MessageSender"));
ovmL2ToL1MessagePasser = iOVM_L2ToL1MessagePasser(resolve("OVM_L2ToL1MessagePasser"));
}
/********************
* Public Functions *
********************/
/**
* Relays a cross domain message to a contract.
* @inheritdoc iOVM_L2CrossDomainMessenger
*/
function relayMessage(
address _target,
address _sender,
bytes memory _message,
uint256 _messageNonce
)
override
public
{
require(
_verifyXDomainMessage() == true,
"Provided message could not be verified."
);
bytes memory xDomainCalldata = _getXDomainCalldata(
_target,
_sender,
_message,
_messageNonce
);
require(
receivedMessages[keccak256(xDomainCalldata)] == false,
"Provided message has already been received."
);
xDomainMessageSender = _sender;
_target.call(_message);
// Messages are considered successfully executed if they complete
// without running out of gas (revert or not). As a result, we can
// ignore the result of the call and always mark the message as
// successfully executed because we won't get here unless we have
// enough gas left over.
receivedMessages[keccak256(xDomainCalldata)] = true;
}
/**
* Sends a cross domain message to the target messenger.
* @inheritdoc iOVM_L2CrossDomainMessenger
*/
function sendMessage(
address _target,
bytes memory _message,
uint256 _gasLimit
)
override
public
{
bytes memory xDomainCalldata = _getXDomainCalldata(
_target,
msg.sender,
_message,
messageNonce
);
_sendXDomainMessage(xDomainCalldata, _gasLimit);
messageNonce += 1;
sentMessages[keccak256(xDomainCalldata)] = true;
}
/**********************
* Internal Functions *
**********************/
/**
* Verifies that a received cross domain message is valid.
* @return _valid Whether or not the message is valid.
*/
function _verifyXDomainMessage()
internal
returns (
bool _valid
)
{
return (
ovmL1MessageSender.getL1MessageSender() == targetMessengerAddress
);
}
/**
* Sends a cross domain message.
* @param _message Message to send.
* @param _gasLimit Gas limit for the provided message.
*/
function _sendXDomainMessage(
bytes memory _message,
uint256 _gasLimit
)
internal
{
ovmL2ToL1MessagePasser.passMessageToL1(_message);
}
}
packages/contracts/build/contracts/OVM/chain/OVM_BaseChain.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Interface Imports */
import { iOVM_BaseChain } from "../../iOVM/chain/iOVM_BaseChain.sol";
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_MerkleUtils } from "../../libraries/utils/Lib_MerkleUtils.sol";
/**
* @title OVM_BaseChain
*/
contract OVM_BaseChain is iOVM_BaseChain {
/*******************************
* Contract Variables: Batches *
*******************************/
bytes32[] internal batches;
uint256 internal totalBatches;
uint256 internal totalElements;
/*************************************
* Public Functions: Batch Retrieval *
*************************************/
/**
* Gets the total number of submitted elements.
* @return _totalElements Total submitted elements.
*/
function getTotalElements()
override
public
view
returns (
uint256 _totalElements
)
{
return totalElements;
}
/**
* Gets the total number of submitted batches.
* @return _totalBatches Total submitted batches.
*/
function getTotalBatches()
override
public
view
returns (
uint256 _totalBatches
)
{
return totalBatches;
}
/****************************************
* Public Functions: Batch Verification *
****************************************/
/**
* Verifies an inclusion proof for a given element.
* @param _element Element to verify.
* @param _batchHeader Header of the batch in which this element was included.
* @param _proof Inclusion proof for the element.
* @return _verified Whether or not the element was included in the batch.
*/
function verifyElement(
bytes calldata _element,
Lib_OVMCodec.ChainBatchHeader memory _batchHeader,
Lib_OVMCodec.ChainInclusionProof memory _proof
)
override
public
view
returns (
bool _verified
)
{
require(
_hashBatchHeader(_batchHeader) == batches[_batchHeader.batchIndex],
"Invalid batch header."
);
require(
Lib_MerkleUtils.verify(
_batchHeader.batchRoot,
_element,
_proof.index,
_proof.siblings
),
"Invalid inclusion proof."
);
return true;
}
/******************************************
* Internal Functions: Batch Modification *
******************************************/
/**
* Appends a batch to the chain.
* @param _batchHeader Batch header to append.
*/
function _appendBatch(
Lib_OVMCodec.ChainBatchHeader memory _batchHeader
)
internal
{
bytes32 batchHeaderHash = _hashBatchHeader(_batchHeader);
batches.push(batchHeaderHash);
totalBatches += 1;
totalElements += _batchHeader.batchSize;
}
/**
* Appends a batch to the chain.
* @param _elements Elements within the batch.
* @param _extraData Any extra data to append to the batch.
*/
function _appendBatch(
bytes[] memory _elements,
bytes memory _extraData
)
internal
{
Lib_OVMCodec.ChainBatchHeader memory batchHeader = Lib_OVMCodec.ChainBatchHeader({
batchIndex: batches.length,
batchRoot: Lib_MerkleUtils.getMerkleRoot(_elements),
batchSize: _elements.length,
prevTotalElements: totalElements,
extraData: _extraData
});
_appendBatch(batchHeader);
}
/**
* Appends a batch to the chain.
* @param _elements Elements within the batch.
*/
function _appendBatch(
bytes[] memory _elements
)
internal
{
_appendBatch(
_elements,
bytes('')
);
}
/**
* Removes a batch from the chain.
* @param _batchHeader Header of the batch to remove.
*/
function _deleteBatch(
Lib_OVMCodec.ChainBatchHeader memory _batchHeader
)
internal
{
require(
_batchHeader.batchIndex < batches.length,
"Invalid batch index."
);
require(
_hashBatchHeader(_batchHeader) == batches[_batchHeader.batchIndex],
"Invalid batch header."
);
totalBatches = _batchHeader.batchIndex;
totalElements = _batchHeader.prevTotalElements;
}
/*********************
* Private Functions *
*********************/
/**
* Calculates a hash for a given batch header.
* @param _batchHeader Header to hash.
* @return _hash Hash of the header.
*/
function _hashBatchHeader(
Lib_OVMCodec.ChainBatchHeader memory _batchHeader
)
private
pure
returns (
bytes32 _hash
)
{
return keccak256(abi.encodePacked(
_batchHeader.batchRoot,
_batchHeader.batchSize,
_batchHeader.prevTotalElements,
_batchHeader.extraData
));
}
}
packages/contracts/build/contracts/OVM/chain/OVM_CanonicalTransactionChain.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
import { Lib_MerkleUtils } from "../../libraries/utils/Lib_MerkleUtils.sol";
/* Interface Imports */
import { iOVM_CanonicalTransactionChain } from "../../iOVM/chain/iOVM_CanonicalTransactionChain.sol";
import { iOVM_L1ToL2TransactionQueue } from "../../iOVM/queue/iOVM_L1ToL2TransactionQueue.sol";
/* Contract Imports */
import { OVM_BaseChain } from "./OVM_BaseChain.sol";
/**
* @title OVM_CanonicalTransactionChain
*/
contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, OVM_BaseChain, Lib_AddressResolver {
/*******************************************
* Contract Variables: Contract References *
*******************************************/
iOVM_L1ToL2TransactionQueue internal ovmL1ToL2TransactionQueue;
/*******************************************
* Contract Variables: Internal Accounting *
*******************************************/
uint256 internal forceInclusionPeriodSeconds;
uint256 internal lastOVMTimestamp;
/***************
* Constructor *
***************/
/**
* @param _libAddressManager Address of the Address Manager.
* @param _forceInclusionPeriodSeconds Period during which only the sequencer can submit.
*/
constructor(
address _libAddressManager,
uint256 _forceInclusionPeriodSeconds
)
Lib_AddressResolver(_libAddressManager)
{
ovmL1ToL2TransactionQueue = iOVM_L1ToL2TransactionQueue(resolve("OVM_L1ToL2TransactionQueue"));
forceInclusionPeriodSeconds = _forceInclusionPeriodSeconds;
}
/****************************************
* Public Functions: Batch Manipulation *
****************************************/
/**
* Appends a batch from the L1ToL2TransactionQueue.
*/
function appendQueueBatch()
override
public
{
require(
ovmL1ToL2TransactionQueue.size() > 0,
"No batches are currently queued to be appended."
);
Lib_OVMCodec.QueueElement memory queueElement = ovmL1ToL2TransactionQueue.peek();
require(
queueElement.timestamp + forceInclusionPeriodSeconds <= block.timestamp,
"Cannot append until the inclusion delay period has elapsed."
);
_appendQueueBatch(queueElement, 1);
ovmL1ToL2TransactionQueue.dequeue();
}
/**
* Appends a sequencer batch.
* @param _batch Batch of transactions to append.
* @param _timestamp Timestamp for the provided batch.
*/
function appendSequencerBatch(
bytes[] memory _batch,
uint256 _timestamp
)
override
public
{
require(
msg.sender == resolve("Sequencer"),
"Function can only be called by the Sequencer."
);
require(
_batch.length > 0,
"Cannot submit an empty batch."
);
require(
_timestamp > lastOVMTimestamp,
"Batch timestamp must be later than the last OVM timestamp."
);
if (ovmL1ToL2TransactionQueue.size() > 0) {
require(
_timestamp <= ovmL1ToL2TransactionQueue.peek().timestamp,
"Older queue batches must be processed before a newer sequencer batch."
);
}
Lib_OVMCodec.QueueElement memory queueElement = Lib_OVMCodec.QueueElement({
timestamp: _timestamp,
batchRoot: Lib_MerkleUtils.getMerkleRoot(_batch),
isL1ToL2Batch: false
});
_appendQueueBatch(queueElement, _batch.length);
}
/******************************************
* Internal Functions: Batch Manipulation *
******************************************/
/**
* Appends a queue batch to the chain.
* @param _queueElement Queue element to append.
* @param _batchSize Number of elements in the batch.
*/
function _appendQueueBatch(
Lib_OVMCodec.QueueElement memory _queueElement,
uint256 _batchSize
)
internal
{
Lib_OVMCodec.ChainBatchHeader memory batchHeader = Lib_OVMCodec.ChainBatchHeader({
batchIndex: getTotalBatches(),
batchRoot: _queueElement.batchRoot,
batchSize: _batchSize,
prevTotalElements: getTotalElements(),
extraData: abi.encodePacked(
_queueElement.timestamp,
_queueElement.isL1ToL2Batch
)
});
_appendBatch(batchHeader);
lastOVMTimestamp = _queueElement.timestamp;
}
}
packages/contracts/build/contracts/OVM/chain/OVM_StateCommitmentChain.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
/* Interface Imports */
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";
/* Contract Imports */
import { OVM_BaseChain } from "./OVM_BaseChain.sol";
/**
* @title OVM_StateCommitmentChain
*/
contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, OVM_BaseChain, Lib_AddressResolver {
/*******************************************
* Contract Variables: Contract References *
*******************************************/
iOVM_CanonicalTransactionChain internal ovmCanonicalTransactionChain;
iOVM_FraudVerifier internal ovmFraudVerifier;
/***************
* Constructor *
***************/
/**
* @param _libAddressManager Address of the Address Manager.
*/
constructor(
address _libAddressManager
)
Lib_AddressResolver(_libAddressManager)
{
ovmCanonicalTransactionChain = iOVM_CanonicalTransactionChain(resolve("OVM_CanonicalTransactionChain"));
ovmFraudVerifier = iOVM_FraudVerifier(resolve("OVM_FraudVerifier"));
}
/****************************************
* Public Functions: Batch Manipulation *
****************************************/
/**
* Appends a batch of state roots to the chain.
* @param _batch Batch of state roots.
*/
function appendStateBatch(
bytes32[] memory _batch
)
override
public
{
require(
_batch.length > 0,
"Cannot submit an empty state batch."
);
require(
getTotalElements() + _batch.length <= ovmCanonicalTransactionChain.getTotalElements(),
"Number of state roots cannot exceed the number of canonical transactions."
);
bytes[] memory elements = new bytes[](_batch.length);
for (uint256 i = 0; i < _batch.length; i++) {
elements[i] = abi.encodePacked(_batch[i]);
}
_appendBatch(elements);
}
/**
* Deletes all state roots after (and including) a given batch.
* @param _batchHeader Header of the batch to start deleting from.
*/
function deleteStateBatch(
Lib_OVMCodec.ChainBatchHeader memory _batchHeader
)
override
public
{
require(
msg.sender == address(ovmFraudVerifier),
"State batches can only be deleted by the OVM_FraudVerifier."
);
_deleteBatch(_batchHeader);
}
}
packages/contracts/build/contracts/OVM/execution/OVM_ExecutionManager.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_EthUtils } from "../../libraries/utils/Lib_EthUtils.sol";
/* Interface Imports */
import { iOVM_ExecutionManager } from "../../iOVM/execution/iOVM_ExecutionManager.sol";
import { iOVM_StateManager } from "../../iOVM/execution/iOVM_StateManager.sol";
import { iOVM_SafetyChecker } from "../../iOVM/execution/iOVM_SafetyChecker.sol";
/* Contract Imports */
import { OVM_ECDSAContractAccount } from "../accounts/OVM_ECDSAContractAccount.sol";
/* Logging */
import { console } from "@nomiclabs/buidler/console.sol";
/**
* @title OVM_ExecutionManager
*/
contract OVM_ExecutionManager is iOVM_ExecutionManager {
/********************************
* External Contract References *
********************************/
iOVM_SafetyChecker public ovmSafetyChecker;
iOVM_StateManager public ovmStateManager;
/*******************************
* Execution Context Variables *
*******************************/
GasMeterConfig internal gasMeterConfig;
GlobalContext internal globalContext;
TransactionContext internal transactionContext;
MessageContext internal messageContext;
TransactionRecord internal transactionRecord;
MessageRecord internal messageRecord;
/**************************
* Gas Metering Constants *
**************************/
address constant GAS_METADATA_ADDRESS = 0x06a506A506a506A506a506a506A506A506A506A5;
uint256 constant NUISANCE_GAS_SLOAD = 20000;
uint256 constant NUISANCE_GAS_SSTORE = 20000;
uint256 constant MIN_NUISANCE_GAS_PER_CONTRACT = 30000;
uint256 constant NUISANCE_GAS_PER_CONTRACT_BYTE = 100;
uint256 constant MIN_GAS_FOR_INVALID_STATE_ACCESS = 30000;
/***************
* Constructor *
***************/
/**
* @param _ovmSafetyChecker Address of the iOVM_SafetyChecker implementation.
*/
constructor(
address _ovmSafetyChecker
) {
ovmSafetyChecker = iOVM_SafetyChecker(_ovmSafetyChecker);
}
/**********************
* Function Modifiers *
**********************/
/**
* Applies a net gas cost refund to a transaction to account for the difference in execution
* between L1 and L2.
* @param _cost Gas cost for the function after the refund.
*/
modifier netGasCost(
uint256 _cost
) {
uint256 gasProvided = gasleft();
_;
uint256 gasUsed = gasProvided - gasleft();
// We want to refund everything *except* the specified cost.
if (_cost < gasUsed) {
transactionRecord.ovmGasRefund += gasUsed - _cost;
}
}
/**
* Makes sure we're not inside a static context.
*/
modifier notStatic() {
if (messageContext.isStatic == true) {
_revertWithFlag(RevertFlag.STATIC_VIOLATION);
}
_;
}
/************************************
* Transaction Execution Entrypoint *
************************************/
/**
* Starts the execution of a transaction via the OVM_ExecutionManager.
* @param _transaction Transaction data to be executed.
* @param _ovmStateManager iOVM_StateManager implementation providing account state.
*/
function run(
Lib_OVMCodec.Transaction memory _transaction,
address _ovmStateManager
)
override
public
{
// Store our OVM_StateManager instance (significantly easier than attempting to pass the address
// around in calldata).
ovmStateManager = iOVM_StateManager(_ovmStateManager);
// Check whether we need to start a new epoch, do so if necessary.
_checkNeedsNewEpoch(_transaction.timestamp);
// Make sure the transaction's gas limit is valid. We don't revert here because we reserve
// reverts for INVALID_STATE_ACCESS.
if (_isValidGasLimit(_transaction.gasLimit, _transaction.l1QueueOrigin) == false) {
return;
}
// Initialize the execution context.
_initContext(_transaction);
// Run the transaction, make sure to meter the gas usage.
uint256 gasProvided = gasleft();
ovmCALL(
_transaction.gasLimit - gasMeterConfig.minTransactionGasLimit,
_transaction.entrypoint,
_transaction.data
);
uint256 gasUsed = gasProvided - gasleft();
// Update the cumulative gas based on the amount of gas used.
_updateCumulativeGas(gasUsed, _transaction.l1QueueOrigin);
// Wipe the execution context.
_resetContext();
}
/******************************
* Opcodes: Execution Context *
******************************/
/**
* @notice Overrides CALLER.
* @return _CALLER Address of the CALLER within the current message context.
*/
function ovmCALLER()
override
public
view
returns (
address _CALLER
)
{
return messageContext.ovmCALLER;
}
/**
* @notice Overrides ADDRESS.
* @return _ADDRESS Active ADDRESS within the current message context.
*/
function ovmADDRESS()
override
public
view
returns (
address _ADDRESS
)
{
return messageContext.ovmADDRESS;
}
/**
* @notice Overrides TIMESTAMP.
* @return _TIMESTAMP Value of the TIMESTAMP within the transaction context.
*/
function ovmTIMESTAMP()
override
public
view
returns (
uint256 _TIMESTAMP
)
{
return transactionContext.ovmTIMESTAMP;
}
/**
* @notice Overrides NUMBER.
* @return _NUMBER Value of the NUMBER within the transaction context.
*/
function ovmNUMBER()
override
public
view
returns (
uint256 _NUMBER
)
{
return transactionContext.ovmNUMBER;
}
/**
* @notice Overrides GASLIMIT.
* @return _GASLIMIT Value of the block's GASLIMIT within the transaction context.
*/
function ovmGASLIMIT()
override
public
view
returns (
uint256 _GASLIMIT
)
{
return transactionContext.ovmGASLIMIT;
}
/**
* @notice Overrides CHAINID.
* @return _CHAINID Value of the chain's CHAINID within the global context.
*/
function ovmCHAINID()
override
public
view
returns (
uint256 _CHAINID
)
{
return globalContext.ovmCHAINID;
}
/*********************************
* Opcodes: L2 Execution Context *
*********************************/
/**
* @notice Specifies from which L1 rollup queue this transaction originated from.
* @return _queueOrigin Address of the CALLER within the current message context.
*/
function ovmL1QUEUEORIGIN()
override
public
view
returns (
Lib_OVMCodec.QueueOrigin _queueOrigin
)
{
return transactionContext.ovmL1QUEUEORIGIN;
}
/**
* @notice Specifies what L1 EOA, if any, sent this transaction.
* @return _l1TxOrigin Address of the EOA which send the tx into L2 from L1.
*/
function ovmL1TXORIGIN()
override
public
view
returns (
address _l1TxOrigin
)
{
return transactionContext.ovmL1TXORIGIN;
}
/********************
* Opcodes: Halting *
********************/
/**
* @notice Overrides REVERT.
* @param _data Bytes data to pass along with the REVERT.
*/
function ovmREVERT(
bytes memory _data
)
override
public
{
_revertWithFlag(RevertFlag.INTENTIONAL_REVERT, _data);
}
/******************************
* Opcodes: Contract Creation *
******************************/
/**
* @notice Overrides CREATE.
* @param _bytecode Code to be used to CREATE a new contract.
* @return _contract Address of the created contract.
*/
function ovmCREATE(
bytes memory _bytecode
)
override
public
notStatic
netGasCost(40000 + _bytecode.length * 100)
returns (
address _contract
)
{
// Creator is always the current ADDRESS.
address creator = ovmADDRESS();
// Generate the correct CREATE address.
address contractAddress = Lib_EthUtils.getAddressForCREATE(
creator,
_getAccountNonce(creator)
);
return _createContract(
contractAddress,
_bytecode
);
}
/**
* @notice Overrides CREATE2.
* @param _bytecode Code to be used to CREATE2 a new contract.
* @param _salt Value used to determine the contract's address.
* @return _contract Address of the created contract.
*/
function ovmCREATE2(
bytes memory _bytecode,
bytes32 _salt
)
override
public
notStatic
netGasCost(40000 + _bytecode.length * 100)
returns (
address _contract
)
{
// Creator is always the current ADDRESS.
address creator = ovmADDRESS();
// Generate the correct CREATE2 address.
address contractAddress = Lib_EthUtils.getAddressForCREATE2(
creator,
_bytecode,
_salt
);
return _createContract(
contractAddress,
_bytecode
);
}
/*******************************
* Account Abstraction Opcodes *
******************************/
/**
* Retrieves the nonce of the current ovmADDRESS.
* @return _nonce Nonce of the current contract.
*/
function ovmGETNONCE()
override
public
returns (
uint256 _nonce
)
{
return _getAccountNonce(ovmADDRESS());
}
/**
* Sets the nonce of the current ovmADDRESS.
* @param _nonce New nonce for the current contract.
*/
function ovmSETNONCE(
uint256 _nonce
)
override
public
{
if (_nonce <= ovmGETNONCE()) {
return;
}
_setAccountNonce(ovmADDRESS(), _nonce);
}
/**
* Creates a new EOA contract account, for account abstraction.
* @dev Essentially functions like ovmCREATE or ovmCREATE2, but we can bypass a lot of checks
* because the contract we're creating is trusted (no need to do safety checking or to
* handle unexpected reverts). Doesn't need to return an address because the address is
* assumed to be the user's actual address.
* @param _messageHash Hash of a message signed by some user, for verification.
* @param _v Signature `v` parameter.
* @param _r Signature `r` parameter.
* @param _s Signature `s` parameter.
*/
function ovmCREATEEOA(
bytes32 _messageHash,
uint8 _v,
bytes32 _r,
bytes32 _s
)
override
public
notStatic
{
// Recover the EOA address from the message hash and signature parameters. Since we do the
// hashing in advance, we don't have handle different message hashing schemes. Even if this
// function were to return the wrong address (rather than explicitly returning the zero
// address), the rest of the transaction would simply fail (since there's no EOA account to
// actually execute the transaction).
address eoa = ecrecover(
_messageHash,
(_v - uint8(ovmCHAINID()) * 2) - 8,
_r,
_s
);
// Invalid signature is a case we proactively handle with a revert. We could alternatively
// have this function return a `success` boolean, but this is just easier.
if (eoa == address(0)) {
ovmREVERT(bytes("Signature provided for EOA contract creation is invalid."));
}
// If the user already has an EOA account, then there's no need to perform this operation.
if (_hasEmptyAccount(eoa) == false) {
return;
}
// We always need to initialize the contract with the default account values.
_initPendingAccount(eoa);
// Now actually create the account and get its bytecode. We're not worried about reverts
// (other than out of gas, which we can't capture anyway) because this contract is trusted.
OVM_ECDSAContractAccount eoaContractAccount = new OVM_ECDSAContractAccount();
bytes memory deployedCode = Lib_EthUtils.getCode(address(eoaContractAccount));
// Commit the account with its final values.
_commitPendingAccount(
eoa,
address(eoaContractAccount),
keccak256(deployedCode)
);
}
/*********************************
* Opcodes: Contract Interaction *
*********************************/
/**
* @notice Overrides CALL.
* @param _gasLimit Amount of gas to be passed into this call.
* @param _address Address of the contract to call.
* @param _calldata Data to send along with the call.
* @return _success Whether or not the call returned (rather than reverted).
* @return _returndata Data returned by the call.
*/
function ovmCALL(
uint256 _gasLimit,
address _address,
bytes memory _calldata
)
override
public
netGasCost(100000)
returns (
bool _success,
bytes memory _returndata
)
{
// CALL updates the CALLER and ADDRESS.
MessageContext memory nextMessageContext = messageContext;
nextMessageContext.ovmCALLER = nextMessageContext.ovmADDRESS;
nextMessageContext.ovmADDRESS = _address;
nextMessageContext.isCreation = false;
bool isStaticEntrypoint = false;
return _callContract(
nextMessageContext,
_gasLimit,
_address,
_calldata,
isStaticEntrypoint
);
}
/**
* @notice Overrides STATICCALL.
* @param _gasLimit Amount of gas to be passed into this call.
* @param _address Address of the contract to call.
* @param _calldata Data to send along with the call.
* @return _success Whether or not the call returned (rather than reverted).
* @return _returndata Data returned by the call.
*/
function ovmSTATICCALL(
uint256 _gasLimit,
address _address,
bytes memory _calldata
)
override
public
netGasCost(80000)
returns (
bool _success,
bytes memory _returndata
)
{
// STATICCALL updates the CALLER, updates the ADDRESS, and runs in a static context.
MessageContext memory nextMessageContext = messageContext;
nextMessageContext.ovmCALLER = nextMessageContext.ovmADDRESS;
nextMessageContext.ovmADDRESS = _address;
nextMessageContext.isStatic = true;
nextMessageContext.isCreation = false;
bool isStaticEntrypoint = true;
return _callContract(
nextMessageContext,
_gasLimit,
_address,
_calldata,
isStaticEntrypoint
);
}
/**
* @notice Overrides DELEGATECALL.
* @param _gasLimit Amount of gas to be passed into this call.
* @param _address Address of the contract to call.
* @param _calldata Data to send along with the call.
* @return _success Whether or not the call returned (rather than reverted).
* @return _returndata Data returned by the call.
*/
function ovmDELEGATECALL(
uint256 _gasLimit,
address _address,
bytes memory _calldata
)
override
public
netGasCost(40000)
returns (
bool _success,
bytes memory _returndata
)
{
// DELEGATECALL does not change anything about the message context.
MessageContext memory nextMessageContext = messageContext;
nextMessageContext.isCreation = false;
bool isStaticEntrypoint = false;
return _callContract(
nextMessageContext,
_gasLimit,
_address,
_calldata,
isStaticEntrypoint
);
}
/************************************
* Opcodes: Contract Storage Access *
************************************/
/**
* @notice Overrides SLOAD.
* @param _key 32 byte key of the storage slot to load.
* @return _value 32 byte value of the requested storage slot.
*/
function ovmSLOAD(
bytes32 _key
)
override
public
netGasCost(40000)
returns (
bytes32 _value
)
{
// We always SLOAD from the storage of ADDRESS.
address contractAddress = ovmADDRESS();
return _getContractStorage(
contractAddress,
_key
);
}
/**
* @notice Overrides SSTORE.
* @param _key 32 byte key of the storage slot to set.
* @param _value 32 byte value for the storage slot.
*/
function ovmSSTORE(
bytes32 _key,
bytes32 _value
)
override
public
notStatic
netGasCost(60000)
{
// We always SSTORE to the storage of ADDRESS.
address contractAddress = ovmADDRESS();
_putContractStorage(
contractAddress,
_key,
_value
);
}
/*********************************
* Opcodes: Contract Code Access *
*********************************/
/**
* @notice Overrides EXTCODECOPY.
* @param _contract Address of the contract to copy code from.
* @param _offset Offset in bytes from the start of contract code to copy beyond.
* @param _length Total number of bytes to copy from the contract's code.
* @return _code Bytes of code copied from the requested contract.
*/
function ovmEXTCODECOPY(
address _contract,
uint256 _offset,
uint256 _length
)
override
public
returns (
bytes memory _code
)
{
// `ovmEXTCODECOPY` is the only overridden opcode capable of producing exactly one byte of
// return data. By blocking reads of one byte, we're able to use the condition that an
// OVM_ExecutionManager function return value having a length of exactly one byte indicates
// an error without an explicit revert. If users were able to read a single byte, they
// could forcibly trigger behavior that should only be available to this contract.
uint256 length = _length == 1 ? 2 : _length;
return Lib_EthUtils.getCode(
_getAccountEthAddress(_contract),
_offset,
length
);
}
/**
* @notice Overrides EXTCODESIZE.
* @param _contract Address of the contract to query the size of.
* @return _EXTCODESIZE Size of the requested contract in bytes.
*/
function ovmEXTCODESIZE(
address _contract
)
override
public
returns (
uint256 _EXTCODESIZE
)
{
return Lib_EthUtils.getCodeSize(
_getAccountEthAddress(_contract)
);
}
/**
* @notice Overrides EXTCODEHASH.
* @param _contract Address of the contract to query the hash of.
* @return _EXTCODEHASH Size of the requested contract in bytes.
*/
function ovmEXTCODEHASH(
address _contract
)
override
public
returns (
bytes32 _EXTCODEHASH
)
{
return Lib_EthUtils.getCodeHash(
_getAccountEthAddress(_contract)
);
}
/**************************************
* Public Functions: Execution Safety *
**************************************/
/**
* Performs the logic to create a contract and revert under various potential conditions.
* @dev This function is implemented as `public` because we need to be able to revert a
* contract creation without losing information about exactly *why* the contract reverted.
* In particular, we want to be sure that contracts cannot trigger an INVALID_STATE_ACCESS
* flag and then revert to reset the flag. We're able to do this by making an external
* call from `ovmCREATE` and `ovmCREATE2` to `safeCREATE`, which can capture and relay
* information before reverting.
* @param _address Address of the contract to associate with the one being created.
* @param _bytecode Code to be used to create the new contract.
*/
function safeCREATE(
address _address,
bytes memory _bytecode
)
override
public
{
// Since this function is public, anyone can attempt to directly call it. We need to make
// sure that the OVM_ExecutionManager itself is the only party that can actually try to
// call this function.
if (msg.sender != address(this)) {
return;
}
// We need to be sure that the user isn't trying to use a contract creation to overwrite
// some existing contract. On L1, users will prove that no contract exists at the address
// and the OVM_FraudVerifier will populate the code hash of this address with a special
// value that represents "known to be an empty account."
if (_hasEmptyAccount(_address) == false) {
_revertWithFlag(RevertFlag.CREATE_COLLISION);
}
// Check the creation bytecode against the OVM_SafetyChecker.
if (ovmSafetyChecker.isBytecodeSafe(_bytecode) == false) {
_revertWithFlag(RevertFlag.UNSAFE_BYTECODE);
}
// We always need to initialize the contract with the default account values.
_initPendingAccount(_address);
// We're going into a contract creation, so we need to set this flag to get the correct
// revert behavior.
messageContext.isCreation = true;
// Actually deploy the contract and retrieve its address. This step is hiding a lot of
// complexity because we need to ensure that contract creation *never* reverts by itself.
// We cover this partially by storing a revert flag and returning (instead of reverting)
// when we know that we're inside a contract's creation code.
address ethAddress = Lib_EthUtils.createContract(_bytecode);
// Now reset this flag so we go back to normal revert behavior.
messageContext.isCreation = false;
// Contract creation returns the zero address when it fails, which should only be possible
// if the user intentionally runs out of gas. However, we might still have a bit of gas
// left over since contract calls can only be passed 63/64ths of total gas, so we need to
// explicitly handle this case here.
if (ethAddress == address(0)) {
_revertWithFlag(RevertFlag.CREATE_EXCEPTION);
}
// Here we pull out the revert flag that would've been set during creation code. Now that
// we're out of creation code again, we can just revert normally while passing the flag
// through the revert data.
if (messageRecord.revertFlag != RevertFlag.DID_NOT_REVERT) {
_revertWithFlag(messageRecord.revertFlag);
}
// Again simply checking that the deployed code is safe too. Contracts can generate
// arbitrary deployment code, so there's no easy way to analyze this beforehand.
bytes memory deployedCode = Lib_EthUtils.getCode(ethAddress);
if (ovmSafetyChecker.isBytecodeSafe(deployedCode) == false) {
_revertWithFlag(RevertFlag.UNSAFE_BYTECODE);
}
// Contract creation didn't need to be reverted and the bytecode is safe. We finish up by
// associating the desired address with the newly created contract's code hash and address.
_commitPendingAccount(
_address,
ethAddress,
keccak256(deployedCode)
);
}
/********************************************
* Internal Functions: Contract Interaction *
********************************************/
/**
* Creates a new contract and associates it with some contract address.
* @param _contractAddress Address to associate the created contract with.
* @param _bytecode Bytecode to be used to create the contract.
* @return _created Final OVM contract address.
*/
function _createContract(
address _contractAddress,
bytes memory _bytecode
)
internal
returns (
address _created
)
{
// We always update the nonce of the creating account, even if the creation fails.
_setAccountNonce(ovmADDRESS(), 1);
// We're stepping into a CREATE or CREATE2, so we need to update ADDRESS to point
// to the contract's associated address and CALLER to point to the previous ADDRESS.
MessageContext memory nextMessageContext = messageContext;
nextMessageContext.ovmCALLER = messageContext.ovmADDRESS;
nextMessageContext.ovmADDRESS = _contractAddress;
// Run `safeCREATE` in a new EVM message so that our changes can be reflected even if
// `safeCREATE` reverts.
(bool _success, ) = _handleExternalInteraction(
nextMessageContext,
gasleft(),
address(this),
abi.encodeWithSignature(
"safeCREATE(address,bytes)",
_contractAddress,
_bytecode
),
false
);
// Need to make sure that this flag is reset so that it isn't propagated to creations in
// some parent EVM message.
messageRecord.revertFlag = RevertFlag.DID_NOT_REVERT;
// Yellow paper requires that address returned is zero if the contract deployment fails.
return _success ? _contractAddress : address(0);
}
/**
* Calls the deployed contract associated with a given address.
* @param _nextMessageContext Message context to be used for the call.
* @param _gasLimit Amount of gas to be passed into this call.
* @param _contract Address used to resolve the deployed contract.
* @param _calldata Data to send along with the call.
* @param _isStaticEntrypoint Whether or not this is coming from ovmSTATICCALL.
* @return _success Whether or not the call returned (rather than reverted).
* @return _returndata Data returned by the call.
*/
function _callContract(
MessageContext memory _nextMessageContext,
uint256 _gasLimit,
address _contract,
bytes memory _calldata,
bool _isStaticEntrypoint
)
internal
returns (
bool _success,
bytes memory _returndata
)
{
return _handleExternalInteraction(
_nextMessageContext,
_gasLimit,
_getAccountEthAddress(_contract),
_calldata,
_isStaticEntrypoint
);
}
/**
* Handles the logic of making an external call and parsing revert information.
* @param _nextMessageContext Message context to be used for the call.
* @param _gasLimit Amount of gas to be passed into this call.
* @param _target Address of the contract to call.
* @param _data Data to send along with the call.
* @param _isStaticEntrypoint Whether or not this is coming from ovmSTATICCALL.
* @return _success Whether or not the call returned (rather than reverted).
* @return _returndata Data returned by the call.
*/
function _handleExternalInteraction(
MessageContext memory _nextMessageContext,
uint256 _gasLimit,
address _target,
bytes memory _data,
bool _isStaticEntrypoint
)
internal
returns (
bool _success,
bytes memory _returndata
)
{
// We need to switch over to our next message context for the duration of this call.
MessageContext memory prevMessageContext = messageContext;
_switchMessageContext(prevMessageContext, _nextMessageContext);
// Nuisance gas is a system used to bound the ability for an attacker to make fraud proofs
// expensive by touching a lot of different accounts or storage slots. Since most contracts
// only use a few storage slots during any given transaction, this shouldn't be a limiting
// factor.
uint256 prevNuisanceGasLeft = messageRecord.nuisanceGasLeft;
uint256 nuisanceGasLimit = _getNuisanceGasLimit(_gasLimit);
messageRecord.nuisanceGasLeft = nuisanceGasLimit;
// Make the call and make sure to pass in the gas limit. Another instance of hidden
// complexity. `_target` is guaranteed to be a safe contract, meaning its return/revert
// behavior can be controlled. In particular, we enforce that flags are passed through
// revert data as to retrieve execution metadata that would normally be reverted out of
// existence.
(bool success, bytes memory returndata) = _target.call{gas: _gasLimit}(_data);
// Switch back to the original message context now that we're out of the call.
_switchMessageContext(_nextMessageContext, prevMessageContext);
// Assuming there were no reverts, the message record should be accurate here. We'll update
// this value in the case of a revert.
uint256 nuisanceGasLeft = messageRecord.nuisanceGasLeft;
// Reverts at this point are completely OK, but we need to make a few updates based on the
// information passed through the revert.
if (success == false) {
(
RevertFlag flag,
uint256 nuisanceGasLeftPostRevert,
uint256 ovmGasRefund,
bytes memory returndataFromFlag
) = _decodeRevertData(returndata);
// INVALID_STATE_ACCESS is the only flag that triggers an immediate abort of the
// parent EVM message. This behavior is necessary because INVALID_STATE_ACCESS must
// halt any further transaction execution that could impact the execution result.
if (flag == RevertFlag.INVALID_STATE_ACCESS) {
_revertWithFlag(flag);
}
// STATIC_VIOLATION should be passed all the way back up to the previous ovmSTATICCALL
// in the call stack.
if (
flag == RevertFlag.STATIC_VIOLATION
&& _isStaticEntrypoint == false
) {
_revertWithFlag(flag);
}
// INTENTIONAL_REVERT and UNSAFE_BYTECODE aren't dependent on the input state, so we
// can just handle them like standard reverts. Our only change here is to record the
// gas refund reported by the call (enforced by safety checking).
if (
flag == RevertFlag.INTENTIONAL_REVERT
|| flag == RevertFlag.UNSAFE_BYTECODE
) {
transactionRecord.ovmGasRefund = ovmGasRefund;
}
// INTENTIONAL_REVERT needs to pass up the user-provided return data encoded into the
// flag, *not* the full encoded flag. All other revert types return no data.
if (flag == RevertFlag.INTENTIONAL_REVERT) {
returndata = returndataFromFlag;
} else {
returndata = hex'';
}
// Reverts mean we need to use up whatever "nuisance gas" was used by the call.
// EXCEEDS_NUISANCE_GAS explicitly reduces the remaining nuisance gas for this message
// to zero. OUT_OF_GAS is a "pseudo" flag given that messages return no data when they
// run out of gas, so we have to treat this like EXCEEDS_NUISANCE_GAS. All other flags
// will simply pass up the remaining nuisance gas.
nuisanceGasLeft = nuisanceGasLeftPostRevert;
}
// We need to reset the nuisance gas back to its original value minus the amount used here.
messageRecord.nuisanceGasLeft = prevNuisanceGasLeft - (nuisanceGasLimit - nuisanceGasLeft);
return (
success,
returndata
);
}
/******************************************
* Internal Functions: State Manipulation *
******************************************/
/**
* Checks whether an account exists within the OVM_StateManager.
* @param _address Address of the account to check.
* @return _exists Whether or not the account exists.
*/
function _hasAccount(
address _address
)
internal
returns (
bool _exists
)
{
_checkAccountLoad(_address);
return ovmStateManager.hasAccount(_address);
}
/**
* Checks whether a known empty account exists within the OVM_StateManager.
* @param _address Address of the account to check.
* @return _exists Whether or not the account empty exists.
*/
function _hasEmptyAccount(
address _address
)
internal
returns (
bool _exists
)
{
_checkAccountLoad(_address);
return ovmStateManager.hasEmptyAccount(_address);
}
/**
* Sets the nonce of an account.
* @param _address Address of the account to modify.
* @param _nonce New account nonce.
*/
function _setAccountNonce(
address _address,
uint256 _nonce
)
internal
{
_checkAccountChange(_address);
ovmStateManager.setAccountNonce(_address, _nonce);
}
/**
* Gets the nonce of an account.
* @param _address Address of the account to access.
* @return _nonce Nonce of the account.
*/
function _getAccountNonce(
address _address
)
internal
returns (
uint256 _nonce
)
{
_checkAccountLoad(_address);
return ovmStateManager.getAccountNonce(_address);
}
/**
* Retrieves the Ethereum address of an account.
* @param _address Address of the account to access.
* @return _ethAddress Corresponding Ethereum address.
*/
function _getAccountEthAddress(
address _address
)
internal
returns (
address _ethAddress
)
{
_checkAccountLoad(_address);
return ovmStateManager.getAccountEthAddress(_address);
}
/**
* Creates the default account object for the given address.
* @param _address Address of the account create.
*/
function _initPendingAccount(
address _address
)
internal
{
// Although it seems like `_checkAccountChange` would be more appropriate here, we don't
// actually consider an account "changed" until it's inserted into the state (in this case
// by `_commitPendingAccount`).
_checkAccountLoad(_address);
ovmStateManager.initPendingAccount(_address);
}
/**
* Stores additional relevant data for a new account, thereby "committing" it to the state.
* This function is only called during `ovmCREATE` and `ovmCREATE2` after a successful contract
* creation.
* @param _address Address of the account to commit.
* @param _ethAddress Address of the associated deployed contract.
* @param _codeHash Hash of the code stored at the address.
*/
function _commitPendingAccount(
address _address,
address _ethAddress,
bytes32 _codeHash
)
internal
{
_checkAccountChange(_address);
ovmStateManager.commitPendingAccount(
_address,
_ethAddress,
_codeHash
);
}
/**
* Retrieves the value of a storage slot.
* @param _contract Address of the contract to query.
* @param _key 32 byte key of the storage slot.
* @return _value 32 byte storage slot value.
*/
function _getContractStorage(
address _contract,
bytes32 _key
)
internal
returns (
bytes32 _value
)
{
_checkContractStorageLoad(_contract, _key);
return ovmStateManager.getContractStorage(_contract, _key);
}
/**
* Sets the value of a storage slot.
* @param _contract Address of the contract to modify.
* @param _key 32 byte key of the storage slot.
* @param _value 32 byte storage slot value.
*/
function _putContractStorage(
address _contract,
bytes32 _key,
bytes32 _value
)
internal
{
_checkContractStorageChange(_contract, _key);
ovmStateManager.putContractStorage(_contract, _key, _value);
}
/**
* Validation whenever a contract needs to be loaded. Checks that the account exists, charges
* nuisance gas if the account hasn't been loaded before.
* @param _address Address of the account to load.
*/
function _checkAccountLoad(
address _address
)
internal
{
// See `_checkContractStorageLoad` for more information.
if (gasleft() < MIN_GAS_FOR_INVALID_STATE_ACCESS) {
_revertWithFlag(RevertFlag.OUT_OF_GAS);
}
// See `_checkContractStorageLoad` for more information.
if (ovmStateManager.hasAccount(_address) == false) {
_revertWithFlag(RevertFlag.INVALID_STATE_ACCESS);
}
// Check whether the account has been loaded before and mark it as loaded if not. We need
// this because "nuisance gas" only applies to the first time that an account is loaded.
(
bool _wasAccountAlreadyLoaded
) = ovmStateManager.testAndSetAccountLoaded(_address);
// If we hadn't already loaded the account, then we'll need to charge "nuisance gas" based
// on the size of the contract code.
if (_wasAccountAlreadyLoaded == false) {
_useNuisanceGas(
(Lib_EthUtils.getCodeSize(_getAccountEthAddress(_address)) * NUISANCE_GAS_PER_CONTRACT_BYTE) + MIN_NUISANCE_GAS_PER_CONTRACT
);
}
}
/**
* Validation whenever a contract needs to be changed. Checks that the account exists, charges
* nuisance gas if the account hasn't been changed before.
* @param _address Address of the account to change.
*/
function _checkAccountChange(
address _address
)
internal
{
// Check whether the account has been changed before and mark it as changed if not. We need
// this because "nuisance gas" only applies to the first time that an account is changed.
(
bool _wasAccountAlreadyChanged
) = ovmStateManager.testAndSetAccountChanged(_address);
// If we hadn't already changed the account, then we'll need to charge "nuisance gas" based
// on the size of the contract code.
if (_wasAccountAlreadyChanged == false) {
ovmStateManager.incrementTotalUncommittedAccounts();
_useNuisanceGas(
(Lib_EthUtils.getCodeSize(_getAccountEthAddress(_address)) * NUISANCE_GAS_PER_CONTRACT_BYTE) + MIN_NUISANCE_GAS_PER_CONTRACT
);
}
}
/**
* Validation whenever a slot needs to be loaded. Checks that the account exists, charges
* nuisance gas if the slot hasn't been loaded before.
* @param _contract Address of the account to load from.
* @param _key 32 byte key to load.
*/
function _checkContractStorageLoad(
address _contract,
bytes32 _key
)
internal
{
// Another case of hidden complexity. If we didn't enforce this requirement, then a
// contract could pass in just enough gas to cause the INVALID_STATE_ACCESS check to fail
// on L1 but not on L2. A contract could use this behavior to prevent the
// OVM_ExecutionManager from detecting an invalid state access. Reverting with OUT_OF_GAS
// allows us to also charge for the full message nuisance gas, because you deserve that for
// trying to break the contract in this way.
if (gasleft() < MIN_GAS_FOR_INVALID_STATE_ACCESS) {
_revertWithFlag(RevertFlag.OUT_OF_GAS);
}
// We need to make sure that the transaction isn't trying to access storage that hasn't
// been provided to the OVM_StateManager. We'll immediately abort if this is the case.
// We know that we have enough gas to do this check because of the above test.
if (ovmStateManager.hasContractStorage(_contract, _key) == false) {
_revertWithFlag(RevertFlag.INVALID_STATE_ACCESS);
}
// Check whether the slot has been loaded before and mark it as loaded if not. We need
// this because "nuisance gas" only applies to the first time that a slot is loaded.
(
bool _wasContractStorageAlreadyLoaded
) = ovmStateManager.testAndSetContractStorageLoaded(_contract, _key);
// If we hadn't already loaded the account, then we'll need to charge some fixed amount of
// "nuisance gas".
if (_wasContractStorageAlreadyLoaded == false) {
_useNuisanceGas(NUISANCE_GAS_SLOAD);
}
}
/**
* Validation whenever a slot needs to be changed. Checks that the account exists, charges
* nuisance gas if the slot hasn't been changed before.
* @param _contract Address of the account to change.
* @param _key 32 byte key to change.
*/
function _checkContractStorageChange(
address _contract,
bytes32 _key
)
internal
{
// See `_checkContractStorageLoad` for more information.
if (gasleft() < MIN_GAS_FOR_INVALID_STATE_ACCESS) {
_revertWithFlag(RevertFlag.OUT_OF_GAS);
}
// See `_checkContractStorageLoad` for more information.
if (ovmStateManager.hasContractStorage(_contract, _key) == false) {
_revertWithFlag(RevertFlag.INVALID_STATE_ACCESS);
}
// Check whether the slot has been changed before and mark it as changed if not. We need
// this because "nuisance gas" only applies to the first time that a slot is changed.
(
bool _wasContractStorageAlreadyChanged
) = ovmStateManager.testAndSetContractStorageChanged(_contract, _key);
// If we hadn't already changed the account, then we'll need to charge some fixed amount of
// "nuisance gas".
if (_wasContractStorageAlreadyChanged == false) {
ovmStateManager.incrementTotalUncommittedContractStorage();
_useNuisanceGas(NUISANCE_GAS_SSTORE);
}
}
/************************************
* Internal Functions: Revert Logic *
************************************/
/**
* Simple encoding for revert data.
* @param _flag Flag to revert with.
* @param _data Additional user-provided revert data.
* @return _revertdata Encoded revert data.
*/
function _encodeRevertData(
RevertFlag _flag,
bytes memory _data
)
internal
returns (
bytes memory _revertdata
)
{
// Out of gas and create exceptions will fundamentally return no data, so simulating it shouldn't either.
if (
_flag == RevertFlag.OUT_OF_GAS
|| _flag == RevertFlag.CREATE_EXCEPTION
) {
return bytes('');
}
// INVALID_STATE_ACCESS doesn't need to return any data other than the flag.
if (_flag == RevertFlag.INVALID_STATE_ACCESS) {
return abi.encode(
_flag,
0,
0,
bytes('')
);
}
// Just ABI encode the rest of the parameters.
return abi.encode(
_flag,
messageRecord.nuisanceGasLeft,
transactionRecord.ovmGasRefund,
_data
);
}
/**
* Simple decoding for revert data.
* @param _revertdata Revert data to decode.
* @return _flag Flag used to revert.
* @return _nuisanceGasLeft Amount of nuisance gas unused by the message.
* @return _ovmGasRefund Amount of gas refunded during the message.
* @return _data Additional user-provided revert data.
*/
function _decodeRevertData(
bytes memory _revertdata
)
internal
returns (
RevertFlag _flag,
uint256 _nuisanceGasLeft,
uint256 _ovmGasRefund,
bytes memory _data
)
{
// A length of zero means the call ran out of gas, just return empty data.
if (_revertdata.length == 0) {
return (
RevertFlag.OUT_OF_GAS,
0,
0,
bytes('')
);
}
// ABI decode the incoming data.
return abi.decode(_revertdata, (RevertFlag, uint256, uint256, bytes));
}
/**
* Causes a message to revert or abort.
* @param _flag Flag to revert with.
* @param _data Additional user-provided data.
*/
function _revertWithFlag(
RevertFlag _flag,
bytes memory _data
)
internal
{
// We don't want to revert when we're inside a CREATE or CREATE2, because those opcodes
// fail silently (we can't pass any data upwards). Instead, we set a flag and return a
// *single* byte, something the OVM_ExecutionManager will not return in any other case.
// We're thereby allowed to communicate failure without allowing contracts to trick us into
// thinking there was a failure.
if (messageContext.isCreation) {
messageRecord.revertFlag = _flag;
assembly {
return(0, 1)
}
}
// If we're not inside a CREATE or CREATE2, we can simply encode the necessary data and
// revert normally.
bytes memory revertdata = _encodeRevertData(
_flag,
_data
);
assembly {
revert(add(revertdata, 0x20), mload(revertdata))
}
}
/**
* Causes a message to revert or abort.
* @param _flag Flag to revert with.
*/
function _revertWithFlag(
RevertFlag _flag
)
internal
{
_revertWithFlag(_flag, bytes(''));
}
/******************************************
* Internal Functions: Nuisance Gas Logic *
******************************************/
/**
* Computes the nuisance gas limit from the gas limit.
* @dev This function is currently using a naive implementation whereby the nuisance gas limit
* is set to exactly equal the lesser of the gas limit or remaining gas. It's likely that
* this implementation is perfectly fine, but we may change this formula later.
* @param _gasLimit Gas limit to compute from.
* @return _nuisanceGasLimit Computed nuisance gas limit.
*/
function _getNuisanceGasLimit(
uint256 _gasLimit
)
internal
view
returns (
uint256 _nuisanceGasLimit
)
{
return _gasLimit < gasleft() ? _gasLimit : gasleft();
}
/**
* Uses a certain amount of nuisance gas.
* @param _amount Amount of nuisance gas to use.
*/
function _useNuisanceGas(
uint256 _amount
)
internal
{
// Essentially the same as a standard OUT_OF_GAS, except we also retain a record of the gas
// refund to be given at the end of the transaction.
if (messageRecord.nuisanceGasLeft < _amount) {
_revertWithFlag(RevertFlag.EXCEEDS_NUISANCE_GAS);
}
messageRecord.nuisanceGasLeft -= _amount;
}
/************************************
* Internal Functions: Gas Metering *
************************************/
/**
* Checks whether a transaction needs to start a new epoch and does so if necessary.
* @param _timestamp Transaction timestamp.
*/
function _checkNeedsNewEpoch(
uint256 _timestamp
)
internal
{
if (
_timestamp >= (
_getGasMetadata(GasMetadataKey.CURRENT_EPOCH_START_TIMESTAMP)
+ gasMeterConfig.secondsPerEpoch
)
) {
_putGasMetadata(
GasMetadataKey.CURRENT_EPOCH_START_TIMESTAMP,
_timestamp
);
_putGasMetadata(
GasMetadataKey.PREV_EPOCH_SEQUENCER_QUEUE_GAS,
_getGasMetadata(
GasMetadataKey.CUMULATIVE_SEQUENCER_QUEUE_GAS
)
);
_putGasMetadata(
GasMetadataKey.PREV_EPOCH_L1TOL2_QUEUE_GAS,
_getGasMetadata(
GasMetadataKey.CUMULATIVE_L1TOL2_QUEUE_GAS
)
);
}
}
/**
* Validates the gas limit for a given transaction.
* @param _gasLimit Gas limit provided by the transaction.
* @param _queueOrigin Queue from which the transaction orginated.
* @return _valid Whether or not the gas limit is valid.
*/
function _isValidGasLimit(
uint256 _gasLimit,
Lib_OVMCodec.QueueOrigin _queueOrigin
)
internal
returns (
bool _valid
)
{
if (_gasLimit > gasMeterConfig.maxTransactionGasLimit) {
return false;
}
if (_gasLimit < gasMeterConfig.minTransactionGasLimit) {
return false;
}
GasMetadataKey cumulativeGasKey;
GasMetadataKey prevEpochGasKey;
if (_queueOrigin == Lib_OVMCodec.QueueOrigin.SEQUENCER_QUEUE) {
cumulativeGasKey = GasMetadataKey.CUMULATIVE_SEQUENCER_QUEUE_GAS;
prevEpochGasKey = GasMetadataKey.PREV_EPOCH_SEQUENCER_QUEUE_GAS;
} else {
cumulativeGasKey = GasMetadataKey.CUMULATIVE_L1TOL2_QUEUE_GAS;
prevEpochGasKey = GasMetadataKey.PREV_EPOCH_L1TOL2_QUEUE_GAS;
}
return (
(
_getGasMetadata(cumulativeGasKey)
- _getGasMetadata(prevEpochGasKey)
+ _gasLimit
) > gasMeterConfig.maxGasPerQueuePerEpoch
);
}
/**
* Updates the cumulative gas after a transaction.
* @param _gasUsed Gas used by the transaction.
* @param _queueOrigin Queue from which the transaction orginated.
*/
function _updateCumulativeGas(
uint256 _gasUsed,
Lib_OVMCodec.QueueOrigin _queueOrigin
)
internal
{
GasMetadataKey cumulativeGasKey;
if (_queueOrigin == Lib_OVMCodec.QueueOrigin.SEQUENCER_QUEUE) {
cumulativeGasKey = GasMetadataKey.CUMULATIVE_SEQUENCER_QUEUE_GAS;
} else {
cumulativeGasKey = GasMetadataKey.CUMULATIVE_L1TOL2_QUEUE_GAS;
}
_putGasMetadata(
cumulativeGasKey,
(
_getGasMetadata(cumulativeGasKey)
+ gasMeterConfig.minTransactionGasLimit
+ _gasUsed
- transactionRecord.ovmGasRefund
)
);
}
/**
* Retrieves the value of a gas metadata key.
* @param _key Gas metadata key to retrieve.
* @return _value Value stored at the given key.
*/
function _getGasMetadata(
GasMetadataKey _key
)
internal
returns (
uint256 _value
)
{
return uint256(_getContractStorage(
GAS_METADATA_ADDRESS,
bytes32(uint256(_key))
));
}
/**
* Sets the value of a gas metadata key.
* @param _key Gas metadata key to set.
* @param _value Value to store at the given key.
*/
function _putGasMetadata(
GasMetadataKey _key,
uint256 _value
)
internal
{
_putContractStorage(
GAS_METADATA_ADDRESS,
bytes32(uint256(_key)),
bytes32(uint256(_value))
);
}
/*****************************************
* Internal Functions: Execution Context *
*****************************************/
/**
* Swaps over to a new message context.
* @param _prevMessageContext Context we're switching from.
* @param _nextMessageContext Context we're switching to.
*/
function _switchMessageContext(
MessageContext memory _prevMessageContext,
MessageContext memory _nextMessageContext
)
internal
{
// Avoid unnecessary the SSTORE.
if (_prevMessageContext.ovmCALLER != _nextMessageContext.ovmCALLER) {
messageContext.ovmCALLER = _nextMessageContext.ovmCALLER;
}
// Avoid unnecessary the SSTORE.
if (_prevMessageContext.ovmADDRESS != _nextMessageContext.ovmADDRESS) {
messageContext.ovmADDRESS = _nextMessageContext.ovmADDRESS;
}
// Avoid unnecessary the SSTORE.
if (_prevMessageContext.isStatic != _nextMessageContext.isStatic) {
messageContext.isStatic = _nextMessageContext.isStatic;
}
// Avoid unnecessary the SSTORE.
if (_prevMessageContext.isCreation != _nextMessageContext.isCreation) {
messageContext.isCreation = _nextMessageContext.isCreation;
}
}
/**
* Initializes the execution context.
* @param _transaction OVM transaction being executed.
*/
function _initContext(
Lib_OVMCodec.Transaction memory _transaction
)
internal
{
transactionContext.ovmTIMESTAMP = _transaction.timestamp;
transactionContext.ovmNUMBER = _transaction.number;
transactionContext.ovmTXGASLIMIT = _transaction.gasLimit;
transactionContext.ovmL1QUEUEORIGIN = _transaction.l1QueueOrigin;
transactionContext.ovmL1TXORIGIN = _transaction.l1Txorigin;
transactionContext.ovmGASLIMIT = gasMeterConfig.maxGasPerQueuePerEpoch;
}
/**
* Resets the transaction and message context.
*/
function _resetContext()
internal
{
transactionContext.ovmL1TXORIGIN = address(0);
transactionContext.ovmTIMESTAMP = 0;
transactionContext.ovmNUMBER = 0;
transactionContext.ovmGASLIMIT = 0;
transactionContext.ovmTXGASLIMIT = 0;
transactionContext.ovmL1QUEUEORIGIN = Lib_OVMCodec.QueueOrigin.SEQUENCER_QUEUE;
transactionRecord.ovmGasRefund = 0;
messageContext.ovmCALLER = address(0);
messageContext.ovmADDRESS = address(0);
messageContext.isStatic = false;
messageRecord.nuisanceGasLeft = 0;
messageRecord.revertFlag = RevertFlag.DID_NOT_REVERT;
}
}
packages/contracts/build/contracts/OVM/execution/OVM_SafetyChecker.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/* Interface Imports */
import { iOVM_SafetyChecker } from "../../iOVM/execution/iOVM_SafetyChecker.sol";
/**
* @title OVM_SafetyChecker
*/
contract OVM_SafetyChecker is iOVM_SafetyChecker {
/********************
* Public Functions *
********************/
/**
* Checks that a given bytecode string is considered safe.
* @param _bytecode Bytecode string to check.
* @return _safe Whether or not the bytecode is safe.
*/
function isBytecodeSafe(
bytes memory _bytecode
)
override
public
view
returns (
bool _safe
)
{
return true;
}
}
packages/contracts/build/contracts/OVM/execution/OVM_StateManager.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
/* Interface Imports */
import { iOVM_StateManager } from "../../iOVM/execution/iOVM_StateManager.sol";
/**
* @title OVM_StateManager
*/
contract OVM_StateManager is iOVM_StateManager {
/**********************
* Contract Constants *
**********************/
bytes32 constant internal EMPTY_ACCOUNT_CODE_HASH = 0x00004B1DC0DE000000004B1DC0DE000000004B1DC0DE000000004B1DC0DE0000;
bytes32 constant internal STORAGE_XOR_VALUE = 0xFEEDFACECAFEBEEFFEEDFACECAFEBEEFFEEDFACECAFEBEEFFEEDFACECAFEBEEF;
/*******************************************
* Contract Variables: Contract References *
*******************************************/
address internal owner;
address internal ovmExecutionManager;
/****************************************
* Contract Variables: Internal Storage *
****************************************/
mapping (address => Lib_OVMCodec.Account) internal accounts;
mapping (address => mapping (bytes32 => bytes32)) internal contractStorage;
mapping (address => mapping (bytes32 => bool)) internal verifiedContractStorage;
mapping (bytes32 => ItemState) internal itemStates;
uint256 internal totalUncommittedAccounts;
uint256 internal totalUncommittedContractStorage;
/***************
* Constructor *
***************/
/**
* @param _owner Address of the owner of this contract.
*/
constructor(
address _owner
) {
owner = _owner;
}
/**********************
* Function Modifiers *
**********************/
/**
* Simple authentication, this contract should only be accessible to the owner or to the
* OVM_ExecutionManager during the transaction execution process.
*/
modifier authenticated() {
require(
msg.sender == owner || msg.sender == ovmExecutionManager,
"Function can only be called by authenticated addresses"
);
_;
}
/***************************
* Public Functions: Setup *
***************************/
/**
* Sets the address of the OVM_ExecutionManager.
* @param _ovmExecutionManager Address of the OVM_ExecutionManager.
*/
function setExecutionManager(
address _ovmExecutionManager
)
override
public
authenticated
{
ovmExecutionManager = _ovmExecutionManager;
}
/************************************
* Public Functions: Account Access *
************************************/
/**
* Inserts an account into the state.
* @param _address Address of the account to insert.
* @param _account Account to insert for the given address.
*/
function putAccount(
address _address,
Lib_OVMCodec.Account memory _account
)
override
public
authenticated
{
accounts[_address] = _account;
}
/**
* Retrieves an account from the state.
* @param _address Address of the account to retrieve.
* @return _account Account for the given address.
*/
function getAccount(address _address)
override
public
view
returns (
Lib_OVMCodec.Account memory _account
)
{
return accounts[_address];
}
/**
* Checks whether the state has a given account.
* @param _address Address of the account to check.
* @return _exists Whether or not the state has the account.
*/
function hasAccount(
address _address
)
override
public
view
returns (
bool _exists
)
{
return accounts[_address].codeHash != bytes32(0);
}
/**
* Checks whether the state has a given known empty account.
* @param _address Address of the account to check.
* @return _exists Whether or not the state has the empty account.
*/
function hasEmptyAccount(
address _address
)
override
public
view
returns (
bool _exists
)
{
return accounts[_address].codeHash == EMPTY_ACCOUNT_CODE_HASH;
}
/**
* Sets the nonce of an account.
* @param _address Address of the account to modify.
* @param _nonce New account nonce.
*/
function setAccountNonce(
address _address,
uint256 _nonce
)
override
public
authenticated
{
accounts[_address].nonce = _nonce;
}
/**
* Gets the nonce of an account.
* @param _address Address of the account to access.
* @return _nonce Nonce of the account.
*/
function getAccountNonce(
address _address
)
override
public
view
returns (
uint256 _nonce
)
{
return accounts[_address].nonce;
}
/**
* Retrieves the Ethereum address of an account.
* @param _address Address of the account to access.
* @return _ethAddress Corresponding Ethereum address.
*/
function getAccountEthAddress(
address _address
)
override
public
view
returns (
address _ethAddress
)
{
return accounts[_address].ethAddress;
}
/**
* Initializes a pending account (during CREATE or CREATE2) with the default values.
* @param _address Address of the account to initialize.
*/
function initPendingAccount(
address _address
)
override
public
authenticated
{
Lib_OVMCodec.Account storage account = accounts[_address];
account.nonce = 1;
account.codeHash = keccak256(hex'80');
account.isFresh = true;
}
/**
* Finalizes the creation of a pending account (during CREATE or CREATE2).
* @param _address Address of the account to finalize.
* @param _ethAddress Address of the account's associated contract on Ethereum.
* @param _codeHash Hash of the account's code.
*/
function commitPendingAccount(
address _address,
address _ethAddress,
bytes32 _codeHash
)
override
public
authenticated
{
Lib_OVMCodec.Account storage account = accounts[_address];
account.ethAddress = _ethAddress;
account.codeHash = _codeHash;
}
/**
* Checks whether an account has already been retrieved, and marks it as retrieved if not.
* @param _address Address of the account to check.
* @return _wasAccountAlreadyLoaded Whether or not the account was already loaded.
*/
function testAndSetAccountLoaded(
address _address
)
override
public
authenticated
returns (
bool _wasAccountAlreadyLoaded
)
{
return _testAndSetItemState(
keccak256(abi.encodePacked(_address)),
ItemState.ITEM_LOADED
);
}
/**
* Checks whether an account has already been modified, and marks it as modified if not.
* @param _address Address of the account to check.
* @return _wasAccountAlreadyChanged Whether or not the account was already modified.
*/
function testAndSetAccountChanged(
address _address
)
override
public
authenticated
returns (
bool _wasAccountAlreadyChanged
)
{
return _testAndSetItemState(
keccak256(abi.encodePacked(_address)),
ItemState.ITEM_CHANGED
);
}
/**
* Attempts to mark an account as committed.
* @param _address Address of the account to commit.
* @return _wasAccountCommitted Whether or not the account was committed.
*/
function commitAccount(
address _address
)
override
public
authenticated
returns (
bool _wasAccountCommitted
)
{
bytes32 item = keccak256(abi.encodePacked(_address));
if (itemStates[item] != ItemState.ITEM_CHANGED) {
return false;
}
itemStates[item] = ItemState.ITEM_COMMITTED;
totalUncommittedAccounts -= 1;
return true;
}
/**
* Increments the total number of uncommitted accounts.
*/
function incrementTotalUncommittedAccounts()
override
public
authenticated
{
totalUncommittedAccounts += 1;
}
/**
* Gets the total number of uncommitted accounts.
* @return _total Total uncommitted accounts.
*/
function getTotalUncommittedAccounts()
override
public
view
returns (
uint256 _total
)
{
return totalUncommittedAccounts;
}
/************************************
* Public Functions: Storage Access *
************************************/
/**
* Changes a contract storage slot value.
* @param _contract Address of the contract to modify.
* @param _key 32 byte storage slot key.
* @param _value 32 byte storage slot value.
*/
function putContractStorage(
address _contract,
bytes32 _key,
bytes32 _value
)
override
public
authenticated
{
// A hilarious optimization. `SSTORE`ing a value of `bytes32(0)` is common enough that it's
// worth populating this with a non-zero value in advance (during the fraud proof
// initialization phase) to cut the execution-time cost down to 5000 gas.
contractStorage[_contract][_key] = _value ^ STORAGE_XOR_VALUE;
// Only used when initially populating the contract storage. OVM_ExecutionManager will
// perform a `hasContractStorage` INVALID_STATE_ACCESS check before putting any contract
// storage because writing to zero when the actual value is nonzero causes a gas
// discrepancy. Could be moved into a new `putVerifiedContractStorage` function, or
// something along those lines.
if (verifiedContractStorage[_contract][_key] == false) {
verifiedContractStorage[_contract][_key] = true;
}
}
/**
* Retrieves a contract storage slot value.
* @param _contract Address of the contract to access.
* @param _key 32 byte storage slot key.
* @return _value 32 byte storage slot value.
*/
function getContractStorage(
address _contract,
bytes32 _key
)
override
public
view
returns (
bytes32 _value
)
{
// Storage XOR system doesn't work for newly created contracts that haven't set this
// storage slot value yet.
if (
verifiedContractStorage[_contract][_key] == false
&& accounts[_contract].isFresh
) {
return bytes32(0);
}
// See `putContractStorage` for more information about the XOR here.
return contractStorage[_contract][_key] ^ STORAGE_XOR_VALUE;
}
/**
* Checks whether a contract storage slot exists in the state.
* @param _contract Address of the contract to access.
* @param _key 32 byte storage slot key.
* @return _exists Whether or not the key was set in the state.
*/
function hasContractStorage(
address _contract,
bytes32 _key
)
override
public
view
returns (
bool _exists
)
{
return verifiedContractStorage[_contract][_key] || accounts[_contract].isFresh;
}
/**
* Checks whether a storage slot has already been retrieved, and marks it as retrieved if not.
* @param _contract Address of the contract to check.
* @param _key 32 byte storage slot key.
* @return _wasContractStorageAlreadyLoaded Whether or not the slot was already loaded.
*/
function testAndSetContractStorageLoaded(
address _contract,
bytes32 _key
)
override
public
authenticated
returns (
bool _wasContractStorageAlreadyLoaded
)
{
return _testAndSetItemState(
keccak256(abi.encodePacked(_contract, _key)),
ItemState.ITEM_LOADED
);
}
/**
* Checks whether a storage slot has already been modified, and marks it as modified if not.
* @param _contract Address of the contract to check.
* @param _key 32 byte storage slot key.
* @return _wasContractStorageAlreadyChanged Whether or not the slot was already modified.
*/
function testAndSetContractStorageChanged(
address _contract,
bytes32 _key
)
override
public
authenticated
returns (
bool _wasContractStorageAlreadyChanged
)
{
return _testAndSetItemState(
keccak256(abi.encodePacked(_contract, _key)),
ItemState.ITEM_CHANGED
);
}
/**
* Attempts to mark a storage slot as committed.
* @param _contract Address of the account to commit.
* @param _key 32 byte slot key to commit.
* @return _wasContractStorageCommitted Whether or not the slot was committed.
*/
function commitContractStorage(
address _contract,
bytes32 _key
)
override
public
authenticated
returns (
bool _wasContractStorageCommitted
)
{
bytes32 item = keccak256(abi.encodePacked(_contract, _key));
if (itemStates[item] != ItemState.ITEM_CHANGED) {
return false;
}
itemStates[item] = ItemState.ITEM_COMMITTED;
totalUncommittedContractStorage -= 1;
return true;
}
/**
* Increments the total number of uncommitted storage slots.
*/
function incrementTotalUncommittedContractStorage()
override
public
authenticated
{
totalUncommittedContractStorage += 1;
}
/**
* Gets the total number of uncommitted storage slots.
* @return _total Total uncommitted storage slots.
*/
function getTotalUncommittedContractStorage()
override
public
view
returns (
uint256 _total
)
{
return totalUncommittedContractStorage;
}
/**********************
* Internal Functions *
**********************/
/**
* Checks whether an item is in a particular state (ITEM_LOADED or ITEM_CHANGED) and sets the
* item to the provided state if not.
* @param _item 32 byte item ID to check.
* @param _minItemState Minumum state that must be satisfied by the item.
* @return _wasItemState Whether or not the item was already in the state.
*/
function _testAndSetItemState(
bytes32 _item,
ItemState _minItemState
)
internal
returns (
bool _wasItemState
)
{
bool wasItemState = itemStates[_item] >= _minItemState;
if (wasItemState == false) {
itemStates[_item] = _minItemState;
}
return wasItemState;
}
}
packages/contracts/build/contracts/OVM/execution/OVM_StateManagerFactory.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/* Interface Imports */
import { iOVM_StateManager } from "../../iOVM/execution/iOVM_StateManager.sol";
import { iOVM_StateManagerFactory } from "../../iOVM/execution/iOVM_StateManagerFactory.sol";
/* Contract Imports */
import { OVM_StateManager } from "./OVM_StateManager.sol";
/**
* @title OVM_StateManagerFactory
*/
contract OVM_StateManagerFactory is iOVM_StateManagerFactory {
/***************************************
* Public Functions: Contract Creation *
***************************************/
/**
* Creates a new OVM_StateManager
* @param _owner Owner of the created contract.
* @return _ovmStateManager New OVM_StateManager instance.
*/
function create(
address _owner
)
override
public
returns (
iOVM_StateManager _ovmStateManager
)
{
return new OVM_StateManager(_owner);
}
}
packages/contracts/build/contracts/OVM/precompiles/OVM_DeployerWhitelist.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/* Library Imports */
import { Lib_Bytes32Utils } from "../../libraries/utils/Lib_Bytes32Utils.sol";
/* Interface Imports */
import { iOVM_DeployerWhitelist } from "../../iOVM/precompiles/iOVM_DeployerWhitelist.sol";
import { iOVM_ExecutionManager } from "../../iOVM/execution/iOVM_ExecutionManager.sol";
/**
* @title OVM_DeployerWhitelist
*/
contract OVM_DeployerWhitelist is iOVM_DeployerWhitelist {
/**********************
* Contract Constants *
**********************/
bytes32 internal constant KEY_INITIALIZED = 0x0000000000000000000000000000000000000000000000000000000000000010;
bytes32 internal constant KEY_OWNER = 0x0000000000000000000000000000000000000000000000000000000000000011;
bytes32 internal constant KEY_ALLOW_ARBITRARY_DEPLOYMENT = 0x0000000000000000000000000000000000000000000000000000000000000012;
/**********************
* Function Modifiers *
**********************/
/**
* Blocks functions to anyone except the contract owner.
*/
modifier onlyOwner() {
iOVM_ExecutionManager ovmExecutionManager = iOVM_ExecutionManager(msg.sender);
address owner = Lib_Bytes32Utils.toAddress(
ovmExecutionManager.ovmSLOAD(
KEY_OWNER
)
);
require(
ovmExecutionManager.ovmCALLER() == owner,
"Function can only be called by the owner of this contract."
);
_;
}
/********************
* Public Functions *
********************/
/**
* Initializes the whitelist.
* @param _owner Address of the owner for this contract.
* @param _allowArbitraryDeployment Whether or not to allow arbitrary contract deployment.
*/
function initialize(
address _owner,
bool _allowArbitraryDeployment
)
override
public
{
iOVM_ExecutionManager ovmExecutionManager = iOVM_ExecutionManager(msg.sender);
bool initialized = Lib_Bytes32Utils.toBool(
ovmExecutionManager.ovmSLOAD(KEY_INITIALIZED)
);
if (initialized == true) {
return;
}
ovmExecutionManager.ovmSSTORE(
KEY_INITIALIZED,
Lib_Bytes32Utils.fromBool(true)
);
ovmExecutionManager.ovmSSTORE(
KEY_OWNER,
Lib_Bytes32Utils.fromAddress(_owner)
);
ovmExecutionManager.ovmSSTORE(
KEY_ALLOW_ARBITRARY_DEPLOYMENT,
Lib_Bytes32Utils.fromBool(_allowArbitraryDeployment)
);
}
/**
* Adds or removes an address from the deployment whitelist.
* @param _deployer Address to update permissions for.
* @param _isWhitelisted Whether or not the address is whitelisted.
*/
function setWhitelistedDeployer(
address _deployer,
bool _isWhitelisted
)
override
public
onlyOwner
{
iOVM_ExecutionManager ovmExecutionManager = iOVM_ExecutionManager(msg.sender);
ovmExecutionManager.ovmSSTORE(
Lib_Bytes32Utils.fromAddress(_deployer),
Lib_Bytes32Utils.fromBool(_isWhitelisted)
);
}
/**
* Updates the owner of this contract.
* @param _owner Address of the new owner.
*/
function setOwner(
address _owner
)
override
public
onlyOwner
{
iOVM_ExecutionManager ovmExecutionManager = iOVM_ExecutionManager(msg.sender);
ovmExecutionManager.ovmSSTORE(
KEY_OWNER,
Lib_Bytes32Utils.fromAddress(_owner)
);
}
/**
* Updates the arbitrary deployment flag.
* @param _allowArbitraryDeployment Whether or not to allow arbitrary contract deployment.
*/
function setAllowArbitraryDeployment(
bool _allowArbitraryDeployment
)
override
public
onlyOwner
{
iOVM_ExecutionManager ovmExecutionManager = iOVM_ExecutionManager(msg.sender);
ovmExecutionManager.ovmSSTORE(
KEY_ALLOW_ARBITRARY_DEPLOYMENT,
Lib_Bytes32Utils.fromBool(_allowArbitraryDeployment)
);
}
/**
* Permanently enables arbitrary contract deployment and deletes the owner.
*/
function enableArbitraryContractDeployment()
override
public
onlyOwner
{
setAllowArbitraryDeployment(true);
setOwner(address(0));
}
/**
* Checks whether an address is allowed to deploy contracts.
* @param _deployer Address to check.
* @return _allowed Whether or not the address can deploy contracts.
*/
function isDeployerAllowed(
address _deployer
)
override
public
returns (
bool _allowed
)
{
iOVM_ExecutionManager ovmExecutionManager = iOVM_ExecutionManager(msg.sender);
bool initialized = Lib_Bytes32Utils.toBool(
ovmExecutionManager.ovmSLOAD(KEY_INITIALIZED)
);
if (initialized == false) {
return true;
}
bool allowArbitraryDeployment = Lib_Bytes32Utils.toBool(
ovmExecutionManager.ovmSLOAD(KEY_ALLOW_ARBITRARY_DEPLOYMENT)
);
if (allowArbitraryDeployment == true) {
return true;
}
bool isWhitelisted = Lib_Bytes32Utils.toBool(
ovmExecutionManager.ovmSLOAD(
Lib_Bytes32Utils.fromAddress(_deployer)
)
);
return isWhitelisted;
}
}
packages/contracts/build/contracts/OVM/precompiles/OVM_L1MessageSender.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/* Interface Imports */
import { iOVM_L1MessageSender } from "../../iOVM/precompiles/iOVM_L1MessageSender.sol";
import { iOVM_ExecutionManager } from "../../iOVM/execution/iOVM_ExecutionManager.sol";
/**
* @title OVM_L1MessageSender
*/
contract OVM_L1MessageSender is iOVM_L1MessageSender {
/********************
* Public Functions *
********************/
/**
* @return _l1MessageSender L1 message sender address (msg.sender).
*/
function getL1MessageSender()
override
public
returns (
address _l1MessageSender
)
{
return iOVM_ExecutionManager(msg.sender).ovmL1TXORIGIN();
}
}
packages/contracts/build/contracts/OVM/precompiles/OVM_L2ToL1MessagePasser.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/* Interface Imports */
import { iOVM_L2ToL1MessagePasser } from "../../iOVM/precompiles/iOVM_L2ToL1MessagePasser.sol";
import { iOVM_ExecutionManager } from "../../iOVM/execution/iOVM_ExecutionManager.sol";
/**
* @title OVM_L2ToL1MessagePasser
*/
contract OVM_L2ToL1MessagePasser is iOVM_L2ToL1MessagePasser {
/**********************
* Contract Variables *
**********************/
uint256 internal nonce;
/********************
* Public Functions *
********************/
/**
* Passes a message to L1.
* @param _message Message to pass to L1.
*/
function passMessageToL1(
bytes memory _message
)
override
public
{
// For now, to be trustfully relayed by sequencer to L1, so just emit
// an event for the sequencer to pick up.
emit L2ToL1Message(
nonce,
iOVM_ExecutionManager(msg.sender).ovmCALLER(),
_message
);
nonce = nonce + 1;
}
}
packages/contracts/build/contracts/OVM/queue/OVM_BaseQueue.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
/* Interface Imports */
import { iOVM_BaseQueue } from "../../iOVM/queue/iOVM_BaseQueue.sol";
/**
* @title OVM_BaseQueue
*/
contract OVM_BaseQueue is iOVM_BaseQueue {
/****************************************
* Contract Variables: Internal Storage *
****************************************/
Lib_OVMCodec.QueueElement[] internal queue;
uint256 internal front;
/**********************
* Function Modifiers *
**********************/
/**
* Asserts that the queue is not empty.
*/
modifier notEmpty() {
require(
size() > 0,
"Queue is empty."
);
_;
}
/**********************************
* Public Functions: Queue Access *
**********************************/
/**
* Gets the size of the queue.
* @return _size Number of elements in the queue.
*/
function size()
override
public
view
returns (
uint256 _size
)
{
return front >= queue.length ? 0 : queue.length - front;
}
/**
* Gets the top element of the queue.
* @return _element First element in the queue.
*/
function peek()
override
public
view
notEmpty
returns (
Lib_OVMCodec.QueueElement memory _element
)
{
return queue[front];
}
/******************************************
* Internal Functions: Queue Manipulation *
******************************************/
/**
* Adds an element to the queue.
* @param _element Queue element to add to the queue.
*/
function _enqueue(
Lib_OVMCodec.QueueElement memory _element
)
internal
{
queue.push(_element);
}
/**
* Pops an element from the queue.
* @return _element Queue element popped from the queue.
*/
function _dequeue()
internal
notEmpty
returns (
Lib_OVMCodec.QueueElement memory _element
)
{
_element = queue[front];
delete queue[front];
front += 1;
return _element;
}
}
packages/contracts/build/contracts/OVM/queue/OVM_L1ToL2TransactionQueue.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
/* Interface Imports */
import { iOVM_L1ToL2TransactionQueue } from "../../iOVM/queue/iOVM_L1ToL2TransactionQueue.sol";
/* Contract Imports */
import { OVM_BaseQueue } from "./OVM_BaseQueue.sol";
/**
* @title OVM_L1ToL2TransactionQueue
*/
contract OVM_L1ToL2TransactionQueue is iOVM_L1ToL2TransactionQueue, OVM_BaseQueue, Lib_AddressResolver {
/*******************************************
* Contract Variables: Contract References *
*******************************************/
address internal ovmCanonicalTransactionChain;
/***************
* Constructor *
***************/
/**
* @param _libAddressManager Address of the Address Manager.
*/
constructor(
address _libAddressManager
)
Lib_AddressResolver(_libAddressManager)
{
ovmCanonicalTransactionChain = resolve("OVM_CanonicalTransactionChain");
}
/****************************************
* Public Functions: Queue Manipulation *
****************************************/
/**
* Adds a transaction to the queue.
* @param _target Target contract to send the transaction to.
* @param _gasLimit Gas limit for the given transaction.
* @param _data Transaction data.
*/
function enqueue(
address _target,
uint256 _gasLimit,
bytes memory _data
)
override
public
{
Lib_OVMCodec.QueueElement memory element = Lib_OVMCodec.QueueElement({
timestamp: block.timestamp,
batchRoot: keccak256(abi.encodePacked(
_target,
_gasLimit,
_data
)),
isL1ToL2Batch: true
});
_enqueue(element);
}
/**
* Pops an element from the queue.
*/
function dequeue()
override
public
{
require(
msg.sender == ovmCanonicalTransactionChain,
"Sender is not allowed to enqueue."
);
_dequeue();
}
}
packages/contracts/build/contracts/OVM/verification/OVM_FraudVerifier.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
/* Interface Imports */
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_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 Variables: Contract References *
*******************************************/
iOVM_StateCommitmentChain internal ovmStateCommitmentChain;
iOVM_CanonicalTransactionChain internal ovmCanonicalTransactionChain;
/*******************************************
* Contract Variables: Internal Accounting *
*******************************************/
mapping (bytes32 => iOVM_StateTransitioner) internal transitioners;
/***************
* Constructor *
***************/
/**
* @param _libAddressManager Address of the Address Manager.
*/
constructor(
address _libAddressManager
)
Lib_AddressResolver(_libAddressManager)
{
ovmStateCommitmentChain = iOVM_StateCommitmentChain(resolve("OVM_StateCommitmentChain"));
ovmCanonicalTransactionChain = iOVM_CanonicalTransactionChain(resolve("OVM_CanonicalTransactionChain"));
}
/***************************************
* Public Functions: Transition Status *
***************************************/
/**
* Retrieves the state transitioner for a given root.
* @param _preStateRoot State root to query a transitioner for.
* @return _transitioner Corresponding state transitioner contract.
*/
function getStateTransitioner(
bytes32 _preStateRoot
)
override
public
view
returns (
iOVM_StateTransitioner _transitioner
)
{
return transitioners[_preStateRoot];
}
/****************************************
* Public Functions: Fraud Verification *
****************************************/
/**
* Begins the fraud verification process.
* @param _preStateRoot State root before the fraudulent transaction.
* @param _preStateRootBatchHeader Batch header for the provided pre-state root.
* @param _preStateRootProof Inclusion proof for the provided pre-state root.
* @param _transaction OVM transaction claimed to be fraudulent.
* @param _transactionBatchHeader Batch header for the provided transaction.
* @param _transactionProof Inclusion proof for the provided transaction.
*/
function initializeFraudVerification(
bytes32 _preStateRoot,
Lib_OVMCodec.ChainBatchHeader memory _preStateRootBatchHeader,
Lib_OVMCodec.ChainInclusionProof memory _preStateRootProof,
Lib_OVMCodec.Transaction memory _transaction,
Lib_OVMCodec.ChainBatchHeader memory _transactionBatchHeader,
Lib_OVMCodec.ChainInclusionProof memory _transactionProof
)
override
public
{
if (_hasStateTransitioner(_preStateRoot)) {
return;
}
require(
_verifyStateRoot(
_preStateRoot,
_preStateRootBatchHeader,
_preStateRootProof
),
"Invalid pre-state root inclusion proof."
);
require(
_verifyTransaction(
_transaction,
_transactionBatchHeader,
_transactionProof
),
"Invalid transaction inclusion proof."
);
transitioners[_preStateRoot] = iOVM_StateTransitionerFactory(
resolve("OVM_StateTransitionerFactory")
).create(
address(libAddressManager),
_preStateRootProof.index,
_preStateRoot,
Lib_OVMCodec.hashTransaction(_transaction)
);
}
/**
* Finalizes the fraud verification process.
* @param _preStateRoot State root before the fraudulent transaction.
* @param _preStateRootBatchHeader Batch header for the provided pre-state root.
* @param _preStateRootProof Inclusion proof for the provided pre-state root.
* @param _postStateRoot State root after the fraudulent transaction.
* @param _postStateRootBatchHeader Batch header for the provided post-state root.
* @param _postStateRootProof Inclusion proof for the provided post-state root.
*/
function finalizeFraudVerification(
bytes32 _preStateRoot,
Lib_OVMCodec.ChainBatchHeader memory _preStateRootBatchHeader,
Lib_OVMCodec.ChainInclusionProof memory _preStateRootProof,
bytes32 _postStateRoot,
Lib_OVMCodec.ChainBatchHeader memory _postStateRootBatchHeader,
Lib_OVMCodec.ChainInclusionProof memory _postStateRootProof
)
override
public
{
iOVM_StateTransitioner transitioner = transitioners[_preStateRoot];
require(
transitioner.isComplete() == true,
"State transition process must be completed prior to finalization."
);
require(
_postStateRootProof.index == _preStateRootProof.index + 1,
"Invalid post-state root index."
);
require(
_verifyStateRoot(
_preStateRoot,
_preStateRootBatchHeader,
_preStateRootProof
),
"Invalid pre-state root inclusion proof."
);
require(
_verifyStateRoot(
_postStateRoot,
_postStateRootBatchHeader,
_postStateRootProof
),
"Invalid post-state root inclusion proof."
);
require(
_postStateRoot != transitioner.getPostStateRoot(),
"State transition has not been proven fraudulent."
);
ovmStateCommitmentChain.deleteStateBatch(
_postStateRootBatchHeader
);
}
/************************************
* Internal Functions: Verification *
************************************/
/**
* Checks whether a transitioner already exists for a given pre-state root.
* @param _preStateRoot Pre-state root to check.
* @return _exists Whether or not we already have a transitioner for the root.
*/
function _hasStateTransitioner(
bytes32 _preStateRoot
)
internal
view
returns (
bool _exists
)
{
return address(transitioners[_preStateRoot]) != address(0);
}
/**
* Verifies inclusion of a state root.
* @param _stateRoot State root to verify
* @param _stateRootBatchHeader Batch header for the provided state root.
* @param _stateRootProof Inclusion proof for the provided state root.
* @return _verified Whether or not the root was included.
*/
function _verifyStateRoot(
bytes32 _stateRoot,
Lib_OVMCodec.ChainBatchHeader memory _stateRootBatchHeader,
Lib_OVMCodec.ChainInclusionProof memory _stateRootProof
)
internal
view
returns (
bool _verified
)
{
return ovmStateCommitmentChain.verifyElement(
abi.encodePacked(_stateRoot),
_stateRootBatchHeader,
_stateRootProof
);
}
/**
* Verifies inclusion of a given transaction.
* @param _transaction OVM transaction to verify.
* @param _transactionBatchHeader Batch header for the provided transaction.
* @param _transactionProof Inclusion proof for the provided transaction.
* @return _verified Whether or not the transaction was included.
*/
function _verifyTransaction(
Lib_OVMCodec.Transaction memory _transaction,
Lib_OVMCodec.ChainBatchHeader memory _transactionBatchHeader,
Lib_OVMCodec.ChainInclusionProof memory _transactionProof
)
internal
view
returns (
bool _verified
)
{
return ovmCanonicalTransactionChain.verifyElement(
Lib_OVMCodec.encodeTransaction(_transaction),
_transactionBatchHeader,
_transactionProof
);
}
}
packages/contracts/build/contracts/OVM/verification/OVM_StateTransitioner.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
import { Lib_EthUtils } from "../../libraries/utils/Lib_EthUtils.sol";
import { Lib_EthMerkleTrie } from "../../libraries/trie/Lib_EthMerkleTrie.sol";
/* Interface Imports */
import { iOVM_StateTransitioner } from "../../iOVM/verification/iOVM_StateTransitioner.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";
/**
* @title OVM_StateTransitioner
*/
contract OVM_StateTransitioner is iOVM_StateTransitioner, Lib_AddressResolver {
/*******************
* Data Structures *
*******************/
enum TransitionPhase {
PRE_EXECUTION,
POST_EXECUTION,
COMPLETE
}
/*******************************************
* Contract Variables: Contract References *
*******************************************/
iOVM_ExecutionManager internal ovmExecutionManager;
iOVM_StateManager internal ovmStateManager;
/*******************************************
* Contract Variables: Internal Accounting *
*******************************************/
bytes32 internal preStateRoot;
bytes32 internal postStateRoot;
TransitionPhase internal phase;
uint256 internal stateTransitionIndex;
bytes32 internal transactionHash;
/***************
* Constructor *
***************/
/**
* @param _libAddressManager Address of the Address Manager.
* @param _stateTransitionIndex Index of the state transition being verified.
* @param _preStateRoot State root before the transition was executed.
* @param _transactionHash Hash of the executed transaction.
*/
constructor(
address _libAddressManager,
uint256 _stateTransitionIndex,
bytes32 _preStateRoot,
bytes32 _transactionHash
)
Lib_AddressResolver(_libAddressManager)
{
stateTransitionIndex = _stateTransitionIndex;
preStateRoot = _preStateRoot;
postStateRoot = _preStateRoot;
transactionHash = _transactionHash;
ovmExecutionManager = iOVM_ExecutionManager(resolve("OVM_ExecutionManager"));
ovmStateManager = iOVM_StateManagerFactory(resolve("OVM_StateManagerFactory")).create(address(this));
}
/**********************
* Function Modifiers *
**********************/
/**
* Checks that a function is only run during a specific phase.
* @param _phase Phase the function must run within.
*/
modifier onlyDuringPhase(
TransitionPhase _phase
) {
require(
phase == _phase,
"Function must be called during the correct phase."
);
_;
}
/**********************************
* Public Functions: State Access *
**********************************/
/**
* Retrieves the state root before execution.
* @return _preStateRoot State root before execution.
*/
function getPreStateRoot()
override
public
view
returns (
bytes32 _preStateRoot
)
{
return preStateRoot;
}
/**
* Retrieves the state root after execution.
* @return _postStateRoot State root after execution.
*/
function getPostStateRoot()
override
public
view
returns (
bytes32 _postStateRoot
)
{
return postStateRoot;
}
/**
* Checks whether the transitioner is complete.
* @return _complete Whether or not the transition process is finished.
*/
function isComplete()
override
public
view
returns (
bool _complete
)
{
return phase == TransitionPhase.COMPLETE;
}
/***********************************
* Public Functions: Pre-Execution *
***********************************/
/**
* Allows a user to prove the initial state of a contract.
* @param _ovmContractAddress Address of the contract on the OVM.
* @param _account Claimed account state.
* @param _stateTrieWitness Proof of the account state.
*/
function proveContractState(
address _ovmContractAddress,
Lib_OVMCodec.Account memory _account,
bytes memory _stateTrieWitness
)
override
public
onlyDuringPhase(TransitionPhase.PRE_EXECUTION)
{
require(
_account.codeHash == Lib_EthUtils.getCodeHash(_account.ethAddress),
"Invalid code hash provided."
);
require(
Lib_EthMerkleTrie.proveAccountState(
_ovmContractAddress,
_account,
_stateTrieWitness,
preStateRoot
),
"Invalid account state provided."
);
ovmStateManager.putAccount(
_ovmContractAddress,
_account
);
}
/**
* Allows a user to prove the initial state of a contract storage slot.
* @param _ovmContractAddress Address of the contract on the OVM.
* @param _key Claimed account slot key.
* @param _value Claimed account slot value.
* @param _stateTrieWitness Proof of the account state.
* @param _storageTrieWitness Proof of the storage slot.
*/
function proveStorageSlot(
address _ovmContractAddress,
bytes32 _key,
bytes32 _value,
bytes memory _stateTrieWitness,
bytes memory _storageTrieWitness
)
override
public
onlyDuringPhase(TransitionPhase.PRE_EXECUTION)
{
require(
ovmStateManager.hasAccount(_ovmContractAddress) == true,
"Contract must be verified before proving a storage slot."
);
require(
Lib_EthMerkleTrie.proveAccountStorageSlotValue(
_ovmContractAddress,
_key,
_value,
_stateTrieWitness,
_storageTrieWitness,
preStateRoot
),
"Invalid account state provided."
);
ovmStateManager.putContractStorage(
_ovmContractAddress,
_key,
_value
);
}
/*******************************
* Public Functions: Execution *
*******************************/
/**
* Executes the state transition.
* @param _transaction OVM transaction to execute.
*/
function applyTransaction(
Lib_OVMCodec.Transaction memory _transaction
)
override
public
{
require(
Lib_OVMCodec.hashTransaction(_transaction) == transactionHash,
"Invalid transaction provided."
);
// TODO: Set state manager for EM here.
ovmStateManager.setExecutionManager(resolve("OVM_ExecutionManager"));
ovmExecutionManager.run(_transaction, address(ovmStateManager));
phase = TransitionPhase.POST_EXECUTION;
}
/************************************
* Public Functions: Post-Execution *
************************************/
/**
* Allows a user to commit the final state of a contract.
* @param _ovmContractAddress Address of the contract on the OVM.
* @param _account Claimed account state.
* @param _stateTrieWitness Proof of the account state.
*/
function commitContractState(
address _ovmContractAddress,
Lib_OVMCodec.Account memory _account,
bytes memory _stateTrieWitness
)
override
public
onlyDuringPhase(TransitionPhase.POST_EXECUTION)
{
require(
ovmStateManager.commitAccount(_ovmContractAddress) == true,
"Cannot commit an account that has not been changed."
);
postStateRoot = Lib_EthMerkleTrie.updateAccountState(
_ovmContractAddress,
_account,
_stateTrieWitness,
postStateRoot
);
}
/**
* Allows a user to commit the final state of a contract storage slot.
* @param _ovmContractAddress Address of the contract on the OVM.
* @param _key Claimed account slot key.
* @param _value Claimed account slot value.
* @param _stateTrieWitness Proof of the account state.
* @param _storageTrieWitness Proof of the storage slot.
*/
function commitStorageSlot(
address _ovmContractAddress,
bytes32 _key,
bytes32 _value,
bytes memory _stateTrieWitness,
bytes memory _storageTrieWitness
)
override
public
onlyDuringPhase(TransitionPhase.POST_EXECUTION)
{
require(
ovmStateManager.commitContractStorage(_ovmContractAddress, _key) == true,
"Cannot commit a storage slot that has not been changed."
);
postStateRoot = Lib_EthMerkleTrie.updateAccountStorageSlotValue(
_ovmContractAddress,
_key,
_value,
_stateTrieWitness,
_storageTrieWitness,
postStateRoot
);
}
/**********************************
* Public Functions: Finalization *
**********************************/
/**
* Finalizes the transition process.
*/
function completeTransition()
override
public
onlyDuringPhase(TransitionPhase.POST_EXECUTION)
{
require(
ovmStateManager.getTotalUncommittedAccounts() == 0,
"All accounts must be committed before completing a transition."
);
require(
ovmStateManager.getTotalUncommittedContractStorage() == 0,
"All storage must be committed before completing a transition."
);
phase = TransitionPhase.COMPLETE;
}
}
packages/contracts/build/contracts/OVM/verification/OVM_StateTransitionerFactory.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/* Interface Imports */
import { iOVM_StateTransitioner } from "../../iOVM/verification/iOVM_StateTransitioner.sol";
import { iOVM_StateTransitionerFactory } from "../../iOVM/verification/iOVM_StateTransitionerFactory.sol";
/* Contract Imports */
import { OVM_StateTransitioner } from "./OVM_StateTransitioner.sol";
/**
* @title OVM_StateTransitionerFactory
*/
contract OVM_StateTransitionerFactory is iOVM_StateTransitionerFactory {
/***************************************
* Public Functions: Contract Creation *
***************************************/
/**
* Creates a new OVM_StateTransitioner
* @param _libAddressManager Address of the Address Manager.
* @param _stateTransitionIndex Index of the state transition being verified.
* @param _preStateRoot State root before the transition was executed.
* @param _transactionHash Hash of the executed transaction.
* @return _ovmStateTransitioner New OVM_StateTransitioner instance.
*/
function create(
address _libAddressManager,
uint256 _stateTransitionIndex,
bytes32 _preStateRoot,
bytes32 _transactionHash
)
override
public
returns (
iOVM_StateTransitioner _ovmStateTransitioner
)
{
return new OVM_StateTransitioner(
_libAddressManager,
_stateTransitionIndex,
_preStateRoot,
_transactionHash
);
}
}
packages/contracts/build/contracts/iOVM/accounts/iOVM_ECDSAContractAccount.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
/**
* @title iOVM_ECDSAContractAccount
*/
interface iOVM_ECDSAContractAccount {
/********************
* Public Functions *
********************/
function execute(
bytes memory _transaction,
Lib_OVMCodec.EOASignatureType _signatureType,
uint8 _v,
bytes32 _r,
bytes32 _s
) external returns (bool _success, bytes memory _returndata);
}
packages/contracts/build/contracts/iOVM/bridge/iOVM_BaseCrossDomainMessenger.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/**
* @title iOVM_BaseCrossDomainMessenger
*/
interface iOVM_BaseCrossDomainMessenger {
/********************
* Public Functions *
********************/
/**
* Sets the target messenger address.
* @param _targetMessengerAddress New messenger address.
*/
function setTargetMessengerAddress(
address _targetMessengerAddress
) external;
}
packages/contracts/build/contracts/iOVM/bridge/iOVM_L1CrossDomainMessenger.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
/* Interface Imports */
import { iOVM_BaseCrossDomainMessenger } from "./iOVM_BaseCrossDomainMessenger.sol";
/**
* @title iOVM_L1CrossDomainMessenger
*/
interface iOVM_L1CrossDomainMessenger is iOVM_BaseCrossDomainMessenger {
/*******************
* Data Structures *
*******************/
struct L2MessageInclusionProof {
bytes32 stateRoot;
Lib_OVMCodec.ChainBatchHeader stateRootBatchHeader;
Lib_OVMCodec.ChainInclusionProof stateRootProof;
bytes stateTrieWitness;
bytes storageTrieWitness;
}
/********************
* Public Functions *
********************/
/**
* Relays a cross domain message to a contract.
* @param _target Target contract address.
* @param _sender Message sender address.
* @param _message Message to send to the target.
* @param _messageNonce Nonce for the provided message.
* @param _proof Inclusion proof for the given message.
*/
function relayMessage(
address _target,
address _sender,
bytes memory _message,
uint256 _messageNonce,
L2MessageInclusionProof memory _proof
) external;
/**
* Sends a cross domain message to the target messenger.
* @param _target Target contract address.
* @param _message Message to send to the target.
* @param _gasLimit Gas limit for the provided message.
*/
function sendMessage(
address _target,
bytes memory _message,
uint32 _gasLimit
) external;
/**
* Replays a cross domain message to the target messenger.
* @param _target Target contract address.
* @param _sender Original sender address.
* @param _message Message to send to the target.
* @param _messageNonce Nonce for the provided message.
* @param _gasLimit Gas limit for the provided message.
*/
function replayMessage(
address _target,
address _sender,
bytes memory _message,
uint256 _messageNonce,
uint32 _gasLimit
) external;
}
packages/contracts/build/contracts/iOVM/bridge/iOVM_L2CrossDomainMessenger.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Interface Imports */
import { iOVM_BaseCrossDomainMessenger } from "./iOVM_BaseCrossDomainMessenger.sol";
/**
* @title iOVM_L2CrossDomainMessenger
*/
interface iOVM_L2CrossDomainMessenger is iOVM_BaseCrossDomainMessenger {
/********************
* Public Functions *
********************/
/**
* Relays a cross domain message to a contract.
* @param _target Target contract address.
* @param _sender Message sender address.
* @param _message Message to send to the target.
* @param _messageNonce Nonce for the provided message.
*/
function relayMessage(
address _target,
address _sender,
bytes memory _message,
uint256 _messageNonce
) external;
/**
* Sends a cross domain message to the target messenger.
* @param _target Target contract address.
* @param _message Message to send to the target.
* @param _gasLimit Gas limit for the provided message.
*/
function sendMessage(
address _target,
bytes memory _message,
uint256 _gasLimit
) external;
}
packages/contracts/build/contracts/iOVM/chain/iOVM_BaseChain.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
/**
* @title iOVM_BaseChain
*/
interface iOVM_BaseChain {
/*************************************
* Public Functions: Batch Retrieval *
*************************************/
function getTotalElements() external view returns (uint256 _totalElements);
function getTotalBatches() external view returns (uint256 _totalBatches);
/****************************************
* Public Functions: Batch Verification *
****************************************/
function verifyElement(
bytes calldata _element,
Lib_OVMCodec.ChainBatchHeader calldata _batchHeader,
Lib_OVMCodec.ChainInclusionProof calldata _proof
) external view returns (bool _verified);
}
packages/contracts/build/contracts/iOVM/chain/iOVM_CanonicalTransactionChain.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Interface Imports */
import { iOVM_BaseChain } from "./iOVM_BaseChain.sol";
/**
* @title iOVM_CanonicalTransactionChain
*/
interface iOVM_CanonicalTransactionChain is iOVM_BaseChain {
/****************************************
* Public Functions: Batch Manipulation *
****************************************/
function appendQueueBatch() external;
function appendSequencerBatch(bytes[] calldata _batch, uint256 _timestamp) external;
}
packages/contracts/build/contracts/iOVM/chain/iOVM_StateCommitmentChain.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Interface Imports */
import { iOVM_BaseChain } from "./iOVM_BaseChain.sol";
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
/**
* @title iOVM_StateCommitmentChain
*/
interface iOVM_StateCommitmentChain is iOVM_BaseChain {
/****************************************
* Public Functions: Batch Manipulation *
****************************************/
function appendStateBatch(bytes32[] calldata _batch) external;
function deleteStateBatch(Lib_OVMCodec.ChainBatchHeader memory _batchHeader) external;
}
packages/contracts/build/contracts/iOVM/execution/iOVM_ExecutionManager.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
interface iOVM_ExecutionManager {
/**********
* Enums *
*********/
enum RevertFlag {
DID_NOT_REVERT,
OUT_OF_GAS,
INTENTIONAL_REVERT,
EXCEEDS_NUISANCE_GAS,
INVALID_STATE_ACCESS,
UNSAFE_BYTECODE,
CREATE_COLLISION,
STATIC_VIOLATION,
CREATE_EXCEPTION
}
enum GasMetadataKey {
CURRENT_EPOCH_START_TIMESTAMP,
CUMULATIVE_SEQUENCER_QUEUE_GAS,
CUMULATIVE_L1TOL2_QUEUE_GAS,
PREV_EPOCH_SEQUENCER_QUEUE_GAS,
PREV_EPOCH_L1TOL2_QUEUE_GAS
}
/***********
* Structs *
***********/
struct GasMeterConfig {
uint256 minTransactionGasLimit;
uint256 maxTransactionGasLimit;
uint256 maxGasPerQueuePerEpoch;
uint256 secondsPerEpoch;
}
struct GlobalContext {
uint256 ovmCHAINID;
}
struct TransactionContext {
Lib_OVMCodec.QueueOrigin ovmL1QUEUEORIGIN;
uint256 ovmTIMESTAMP;
uint256 ovmNUMBER;
uint256 ovmGASLIMIT;
uint256 ovmTXGASLIMIT;
address ovmL1TXORIGIN;
}
struct TransactionRecord {
uint256 ovmGasRefund;
}
struct MessageContext {
address ovmCALLER;
address ovmADDRESS;
bool isStatic;
bool isCreation;
}
struct MessageRecord {
uint256 nuisanceGasLeft;
RevertFlag revertFlag;
}
/************************************
* Transaction Execution Entrypoint *
************************************/
function run(
Lib_OVMCodec.Transaction calldata _transaction,
address _txStateManager
) external;
/*******************
* Context Opcodes *
*******************/
function ovmCALLER() external view returns (address _caller);
function ovmADDRESS() external view returns (address _address);
function ovmTIMESTAMP() external view returns (uint256 _timestamp);
function ovmNUMBER() external view returns (uint256 _number);
function ovmGASLIMIT() external view returns (uint256 _gasLimit);
function ovmCHAINID() external view returns (uint256 _chainId);
/**********************
* L2 Context Opcodes *
**********************/
function ovmL1QUEUEORIGIN() external view returns (Lib_OVMCodec.QueueOrigin _queueOrigin);
function ovmL1TXORIGIN() external view returns (address _l1TxOrigin);
/*******************
* Halting Opcodes *
*******************/
function ovmREVERT(bytes memory _data) external;
/*****************************
* Contract Creation Opcodes *
*****************************/
function ovmCREATE(bytes memory _bytecode) external returns (address _contract);
function ovmCREATE2(bytes memory _bytecode, bytes32 _salt) external returns (address _contract);
/*******************************
* Account Abstraction Opcodes *
******************************/
function ovmGETNONCE() external returns (uint256 _nonce);
function ovmSETNONCE(uint256 _nonce) external;
function ovmCREATEEOA(bytes32 _messageHash, uint8 _v, bytes32 _r, bytes32 _s) external;
/****************************
* Contract Calling Opcodes *
****************************/
function ovmCALL(uint256 _gasLimit, address _address, bytes memory _calldata) external returns (bool _success, bytes memory _returndata);
function ovmSTATICCALL(uint256 _gasLimit, address _address, bytes memory _calldata) external returns (bool _success, bytes memory _returndata);
function ovmDELEGATECALL(uint256 _gasLimit, address _address, bytes memory _calldata) external returns (bool _success, bytes memory _returndata);
/****************************
* Contract Storage Opcodes *
****************************/
function ovmSLOAD(bytes32 _key) external returns (bytes32 _value);
function ovmSSTORE(bytes32 _key, bytes32 _value) external;
/*************************
* Contract Code Opcodes *
*************************/
function ovmEXTCODECOPY(address _contract, uint256 _offset, uint256 _length) external returns (bytes memory _code);
function ovmEXTCODESIZE(address _contract) external returns (uint256 _size);
function ovmEXTCODEHASH(address _contract) external returns (bytes32 _hash);
/**************************************
* Public Functions: Execution Safety *
**************************************/
function safeCREATE(address _address, bytes memory _bytecode) external;
}
packages/contracts/build/contracts/iOVM/execution/iOVM_SafetyChecker.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/**
* @title iOVM_SafetyChecker
*/
interface iOVM_SafetyChecker {
/********************
* Public Functions *
********************/
function isBytecodeSafe(bytes memory _bytecode) external view returns (bool _safe);
}
packages/contracts/build/contracts/iOVM/execution/iOVM_StateManager.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
/**
* @title iOVM_StateManager
*/
interface iOVM_StateManager {
/*******************
* Data Structures *
*******************/
enum ItemState {
ITEM_UNTOUCHED,
ITEM_LOADED,
ITEM_CHANGED,
ITEM_COMMITTED
}
/***************************
* Public Functions: Setup *
***************************/
function setExecutionManager(address _ovmExecutionManager) external;
/************************************
* Public Functions: Account Access *
************************************/
function putAccount(address _address, Lib_OVMCodec.Account memory _account) external;
function getAccount(address _address) external view returns (Lib_OVMCodec.Account memory _account);
function hasAccount(address _address) external view returns (bool _exists);
function hasEmptyAccount(address _address) external view returns (bool _exists);
function setAccountNonce(address _address, uint256 _nonce) external;
function getAccountNonce(address _address) external view returns (uint256 _nonce);
function getAccountEthAddress(address _address) external view returns (address _ethAddress);
function initPendingAccount(address _address) external;
function commitPendingAccount(address _address, address _ethAddress, bytes32 _codeHash) external;
function testAndSetAccountLoaded(address _address) external returns (bool _wasAccountAlreadyLoaded);
function testAndSetAccountChanged(address _address) external returns (bool _wasAccountAlreadyChanged);
function commitAccount(address _address) external returns (bool _wasAccountCommitted);
function incrementTotalUncommittedAccounts() external;
function getTotalUncommittedAccounts() external view returns (uint256 _total);
/************************************
* Public Functions: Storage Access *
************************************/
function putContractStorage(address _contract, bytes32 _key, bytes32 _value) external;
function getContractStorage(address _contract, bytes32 _key) external view returns (bytes32 _value);
function hasContractStorage(address _contract, bytes32 _key) external returns (bool _exists);
function testAndSetContractStorageLoaded(address _contract, bytes32 _key) external returns (bool _wasContractStorageAlreadyLoaded);
function testAndSetContractStorageChanged(address _contract, bytes32 _key) external returns (bool _wasContractStorageAlreadyChanged);
function commitContractStorage(address _contract, bytes32 _key) external returns (bool _wasContractStorageCommitted);
function incrementTotalUncommittedContractStorage() external;
function getTotalUncommittedContractStorage() external view returns (uint256 _total);
}
packages/contracts/build/contracts/iOVM/execution/iOVM_StateManagerFactory.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/* Contract Imports */
import { iOVM_StateManager } from "./iOVM_StateManager.sol";
/**
* @title iOVM_StateManagerFactory
*/
interface iOVM_StateManagerFactory {
/***************************************
* Public Functions: Contract Creation *
***************************************/
function create(
address _owner
)
external
returns (
iOVM_StateManager _ovmStateManager
);
}
packages/contracts/build/contracts/iOVM/precompiles/iOVM_DeployerWhitelist.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/**
* @title iOVM_DeployerWhitelist
*/
interface iOVM_DeployerWhitelist {
/********************
* Public Functions *
********************/
function initialize(address _owner, bool _allowArbitraryDeployment) external;
function setWhitelistedDeployer(address _deployer, bool _isWhitelisted) external;
function setOwner(address _newOwner) external;
function setAllowArbitraryDeployment(bool _allowArbitraryDeployment) external;
function enableArbitraryContractDeployment() external;
function isDeployerAllowed(address _deployer) external returns (bool _allowed);
}
packages/contracts/build/contracts/iOVM/precompiles/iOVM_L1MessageSender.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/**
* @title iOVM_L1MessageSender
*/
interface iOVM_L1MessageSender {
/********************
* Public Functions *
********************/
function getL1MessageSender() external returns (address _l1MessageSender);
}
packages/contracts/build/contracts/iOVM/precompiles/iOVM_L2ToL1MessagePasser.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/**
* @title iOVM_L2ToL1MessagePasser
*/
interface iOVM_L2ToL1MessagePasser {
/**********
* Events *
**********/
event L2ToL1Message(
uint _nonce,
address _sender,
bytes _data
);
/********************
* Public Functions *
********************/
function passMessageToL1(bytes memory _message) external;
}
packages/contracts/build/contracts/iOVM/queue/iOVM_BaseQueue.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
/**
* @title iOVM_BaseQueue
*/
interface iOVM_BaseQueue {
/**********************************
* Public Functions: Queue Access *
**********************************/
function size() external view returns (uint256 _size);
function peek() external view returns (Lib_OVMCodec.QueueElement memory _element);
}
packages/contracts/build/contracts/iOVM/queue/iOVM_L1ToL2TransactionQueue.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
/* Interface Imports */
import { iOVM_BaseQueue } from "./iOVM_BaseQueue.sol";
/**
* @title iOVM_L1ToL2TransactionQueue
*/
interface iOVM_L1ToL2TransactionQueue is iOVM_BaseQueue {
/****************************************
* Public Functions: Queue Manipulation *
****************************************/
function enqueue(address _target, uint256 _gasLimit, bytes memory _data) external;
function dequeue() external;
}
packages/contracts/build/contracts/iOVM/verification/iOVM_FraudVerifier.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
/* Interface Imports */
import { iOVM_StateTransitioner } from "./iOVM_StateTransitioner.sol";
/**
* @title iOVM_FraudVerifier
*/
interface iOVM_FraudVerifier {
/***************************************
* Public Functions: Transition Status *
***************************************/
function getStateTransitioner(bytes32 _preStateRoot) external view returns (iOVM_StateTransitioner _transitioner);
/****************************************
* Public Functions: Fraud Verification *
****************************************/
function initializeFraudVerification(
bytes32 _preStateRoot,
Lib_OVMCodec.ChainBatchHeader calldata _preStateRootBatchHeader,
Lib_OVMCodec.ChainInclusionProof calldata _preStateRootProof,
Lib_OVMCodec.Transaction calldata _transaction,
Lib_OVMCodec.ChainBatchHeader calldata _transactionBatchHeader,
Lib_OVMCodec.ChainInclusionProof calldata _transactionProof
) external;
function finalizeFraudVerification(
bytes32 _preStateRoot,
Lib_OVMCodec.ChainBatchHeader calldata _preStateRootBatchHeader,
Lib_OVMCodec.ChainInclusionProof calldata _preStateRootProof,
bytes32 _postStateRoot,
Lib_OVMCodec.ChainBatchHeader calldata _postStateRootBatchHeader,
Lib_OVMCodec.ChainInclusionProof calldata _postStateRootProof
) external;
}
packages/contracts/build/contracts/iOVM/verification/iOVM_StateTransitioner.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
/**
* @title iOVM_StateTransitioner
*/
interface iOVM_StateTransitioner {
/**********************************
* Public Functions: State Access *
**********************************/
function getPreStateRoot() external view returns (bytes32 _preStateRoot);
function getPostStateRoot() external view returns (bytes32 _postStateRoot);
function isComplete() external view returns (bool _complete);
/***********************************
* Public Functions: Pre-Execution *
***********************************/
function proveContractState(
address _ovmContractAddress,
Lib_OVMCodec.Account calldata _account,
bytes calldata _stateTrieWitness
) external;
function proveStorageSlot(
address _ovmContractAddress,
bytes32 _key,
bytes32 _value,
bytes calldata _stateTrieWitness,
bytes calldata _storageTrieWitness
) external;
/*******************************
* Public Functions: Execution *
*******************************/
function applyTransaction(
Lib_OVMCodec.Transaction calldata _transaction
) external;
/************************************
* Public Functions: Post-Execution *
************************************/
function commitContractState(
address _ovmContractAddress,
Lib_OVMCodec.Account calldata _account,
bytes calldata _stateTrieWitness
) external;
function commitStorageSlot(
address _ovmContractAddress,
bytes32 _key,
bytes32 _value,
bytes calldata _stateTrieWitness,
bytes calldata _storageTrieWitness
) external;
/**********************************
* Public Functions: Finalization *
**********************************/
function completeTransition() external;
}
packages/contracts/build/contracts/iOVM/verification/iOVM_StateTransitionerFactory.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/* Contract Imports */
import { iOVM_StateTransitioner } from "./iOVM_StateTransitioner.sol";
/**
* @title iOVM_StateTransitionerFactory
*/
interface iOVM_StateTransitionerFactory {
/***************************************
* Public Functions: Contract Creation *
***************************************/
function create(
address _proxyManager,
uint256 _stateTransitionIndex,
bytes32 _preStateRoot,
bytes32 _transactionHash
)
external
returns (
iOVM_StateTransitioner _ovmStateTransitioner
);
}
packages/contracts/build/contracts/libraries/codec/Lib_OVMCodec.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_RLPReader } from "../rlp/Lib_RLPReader.sol";
/**
* @title Lib_OVMCodec
*/
library Lib_OVMCodec {
/*********
* Enums *
*********/
enum EOASignatureType {
ETH_SIGNED_MESSAGE,
NATIVE_TRANSACTON
}
enum QueueOrigin {
SEQUENCER_QUEUE,
L1TOL2_QUEUE
}
/***********
* Structs *
***********/
struct Account {
uint256 nonce;
uint256 balance;
bytes32 storageRoot;
bytes32 codeHash;
address ethAddress;
bool isFresh;
}
struct EVMAccount {
uint256 nonce;
uint256 balance;
bytes32 storageRoot;
bytes32 codeHash;
}
struct ChainBatchHeader {
uint256 batchIndex;
bytes32 batchRoot;
uint256 batchSize;
uint256 prevTotalElements;
bytes extraData;
}
struct ChainInclusionProof {
uint256 index;
bytes32[] siblings;
}
struct Transaction {
uint256 timestamp;
uint256 number;
QueueOrigin l1QueueOrigin;
address l1Txorigin;
address entrypoint;
uint256 gasLimit;
bytes data;
}
struct ProofMatrix {
bool checkNonce;
bool checkBalance;
bool checkStorageRoot;
bool checkCodeHash;
}
struct QueueElement {
uint256 timestamp;
bytes32 batchRoot;
bool isL1ToL2Batch;
}
struct EOATransaction {
address target;
uint256 nonce;
uint256 gasLimit;
bytes data;
}
/*********************************************
* Internal Functions: Encoding and Decoding *
*********************************************/
/**
* Decodes an EOA transaction (i.e., native Ethereum RLP encoding).
* @param _transaction Encoded EOA transaction.
* @return _decoded Transaction decoded into a struct.
*/
function decodeEOATransaction(
bytes memory _transaction
)
internal
pure
returns (
EOATransaction memory _decoded
)
{
Lib_RLPReader.RLPItem[] memory decoded = Lib_RLPReader.toList(Lib_RLPReader.toRlpItem(_transaction));
return EOATransaction({
nonce: Lib_RLPReader.toUint(decoded[0]),
gasLimit: Lib_RLPReader.toUint(decoded[2]),
target: Lib_RLPReader.toAddress(decoded[3]),
data: Lib_RLPReader.toBytes(decoded[5])
});
}
/**
* Encodes a standard OVM transaction.
* @param _transaction OVM transaction to encode.
* @return _encoded Encoded transaction bytes.
*/
function encodeTransaction(
Transaction memory _transaction
)
internal
pure
returns (
bytes memory _encoded
)
{
return abi.encodePacked(
_transaction.timestamp,
_transaction.number,
_transaction.l1QueueOrigin,
_transaction.l1Txorigin,
_transaction.entrypoint,
_transaction.gasLimit,
_transaction.data
);
}
/**
* Hashes a standard OVM transaction.
* @param _transaction OVM transaction to encode.
* @return _hash Hashed transaction
*/
function hashTransaction(
Transaction memory _transaction
)
internal
pure
returns (
bytes32 _hash
)
{
return keccak256(encodeTransaction(_transaction));
}
}
packages/contracts/build/contracts/libraries/resolver/Lib_AddressManager.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/**
* @title Lib_AddressManager
*/
contract Lib_AddressManager {
/*******************************************
* Contract Variables: Internal Accounting *
*******************************************/
mapping (bytes32 => address) private addresses;
/********************
* Public Functions *
********************/
function setAddress(
string memory _name,
address _address
)
public
{
addresses[_getNameHash(_name)] = _address;
}
function getAddress(
string memory _name
)
public
view
returns (address)
{
return addresses[_getNameHash(_name)];
}
/**********************
* Internal Functions *
**********************/
function _getNameHash(
string memory _name
)
internal
pure
returns (
bytes32 _hash
)
{
return keccak256(abi.encodePacked(_name));
}
}
packages/contracts/build/contracts/libraries/resolver/Lib_AddressResolver.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/* Library Imports */
import { Lib_AddressManager } from "./Lib_AddressManager.sol";
/**
* @title Lib_AddressResolver
*/
contract Lib_AddressResolver {
/*******************************************
* Contract Variables: Contract References *
*******************************************/
Lib_AddressManager internal libAddressManager;
/***************
* Constructor *
***************/
/**
* @param _libAddressManager Address of the Lib_AddressManager.
*/
constructor(
address _libAddressManager
)
public
{
libAddressManager = Lib_AddressManager(_libAddressManager);
}
/********************
* Public Functions *
********************/
function resolve(
string memory _name
)
public
view
returns (
address _contract
)
{
return libAddressManager.getAddress(_name);
}
}
packages/contracts/build/contracts/libraries/rlp/Lib_RLPReader.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/**
* @title RLPReader
* @author Hamdi Allam hamdi.allam97@gmail.com
*/
library Lib_RLPReader {
/*
* Data Structures
*/
struct RLPItem {
uint len;
uint memPtr;
}
/*
* Contract Constants
*/
uint8 constant private STRING_SHORT_START = 0x80;
uint8 constant private STRING_LONG_START = 0xb8;
uint8 constant private LIST_SHORT_START = 0xc0;
uint8 constant private LIST_LONG_START = 0xf8;
uint8 constant private WORD_SIZE = 32;
/*
* Public Functions
*/
/**
* @param item RLP encoded bytes
*/
function toRlpItem(
bytes memory item
)
internal
pure
returns (RLPItem memory)
{
uint memPtr;
assembly {
memPtr := add(item, 0x20)
}
return RLPItem(item.length, memPtr);
}
/**
* @param item RLP encoded bytes
*/
function rlpLen(
RLPItem memory item
)
internal
pure
returns (uint)
{
return item.len;
}
/**
* @param item RLP encoded bytes
*/
function payloadLen(
RLPItem memory item
)
internal
pure
returns (uint)
{
return item.len - _payloadOffset(item.memPtr);
}
/**
* @param item RLP encoded list in bytes
*/
function toList(
RLPItem memory item
)
internal
pure
returns (RLPItem[] memory result)
{
require(isList(item));
uint items = numItems(item);
result = new RLPItem[](items);
uint memPtr = item.memPtr + _payloadOffset(item.memPtr);
uint dataLen;
for (uint i = 0; i < items; i++) {
dataLen = _itemLength(memPtr);
result[i] = RLPItem(dataLen, memPtr);
memPtr = memPtr + dataLen;
}
}
// @return indicator whether encoded payload is a list. negate this function call for isData.
function isList(
RLPItem memory item
)
internal
pure
returns (bool)
{
if (item.len == 0) return false;
uint8 byte0;
uint memPtr = item.memPtr;
assembly {
byte0 := byte(0, mload(memPtr))
}
if (byte0 < LIST_SHORT_START)
return false;
return true;
}
/** RLPItem conversions into data types **/
// @returns raw rlp encoding in bytes
function toRlpBytes(
RLPItem memory item
)
internal
pure
returns (bytes memory)
{
bytes memory result = new bytes(item.len);
if (result.length == 0) return result;
uint ptr;
assembly {
ptr := add(0x20, result)
}
copy(item.memPtr, ptr, item.len);
return result;
}
// any non-zero byte is considered true
function toBoolean(
RLPItem memory item
)
internal
pure
returns (bool)
{
require(item.len == 1);
uint result;
uint memPtr = item.memPtr;
assembly {
result := byte(0, mload(memPtr))
}
return result == 0 ? false : true;
}
function toAddress(
RLPItem memory item
)
internal
pure
returns (address)
{
// 1 byte for the length prefix
require(item.len == 21);
return address(toUint(item));
}
function toUint(
RLPItem memory item
)
internal
pure
returns (uint)
{
require(item.len > 0 && item.len <= 33);
uint offset = _payloadOffset(item.memPtr);
uint len = item.len - offset;
uint result;
uint memPtr = item.memPtr + offset;
assembly {
result := mload(memPtr)
// shfit to the correct location if neccesary
if lt(len, 32) {
result := div(result, exp(256, sub(32, len)))
}
}
return result;
}
// enforces 32 byte length
function toUintStrict(
RLPItem memory item
)
internal
pure
returns (uint)
{
// one byte prefix
require(item.len == 33);
uint result;
uint memPtr = item.memPtr + 1;
assembly {
result := mload(memPtr)
}
return result;
}
function toBytes(
RLPItem memory item
)
internal
pure
returns (bytes memory)
{
require(item.len > 0);
uint offset = _payloadOffset(item.memPtr);
uint len = item.len - offset; // data length
bytes memory result = new bytes(len);
uint destPtr;
assembly {
destPtr := add(0x20, result)
}
copy(item.memPtr + offset, destPtr, len);
return result;
}
/*
* Private Functions
*/
// @return number of payload items inside an encoded list.
function numItems(
RLPItem memory item
)
private
pure
returns (uint)
{
if (item.len == 0) return 0;
uint count = 0;
uint currPtr = item.memPtr + _payloadOffset(item.memPtr);
uint endPtr = item.memPtr + item.len;
while (currPtr < endPtr) {
currPtr = currPtr + _itemLength(currPtr); // skip over an item
count++;
}
return count;
}
// @return entire rlp item byte length
function _itemLength(
uint memPtr
)
private
pure
returns (uint len)
{
uint byte0;
assembly {
byte0 := byte(0, mload(memPtr))
}
if (byte0 < STRING_SHORT_START)
return 1;
else if (byte0 < STRING_LONG_START)
return byte0 - STRING_SHORT_START + 1;
else if (byte0 < LIST_SHORT_START) {
assembly {
let byteLen := sub(byte0, 0xb7) // number of bytes the actual length is
memPtr := add(memPtr, 1) // skip over the first byte
/* 32 byte word size */
let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len
len := add(dataLen, add(byteLen, 1))
}
}
else if (byte0 < LIST_LONG_START) {
return byte0 - LIST_SHORT_START + 1;
}
else {
assembly {
let byteLen := sub(byte0, 0xf7)
memPtr := add(memPtr, 1)
let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length
len := add(dataLen, add(byteLen, 1))
}
}
}
// @return number of bytes until the data
function _payloadOffset(
uint memPtr
)
private
pure
returns (uint)
{
uint byte0;
assembly {
byte0 := byte(0, mload(memPtr))
}
if (byte0 < STRING_SHORT_START)
return 0;
else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START))
return 1;
else if (byte0 < LIST_SHORT_START) // being explicit
return byte0 - (STRING_LONG_START - 1) + 1;
else
return byte0 - (LIST_LONG_START - 1) + 1;
}
/*
* @param src Pointer to source
* @param dest Pointer to destination
* @param len Amount of memory to copy from the source
*/
function copy(
uint src,
uint dest,
uint len
)
private
pure
{
if (len == 0) return;
// copy as many word sizes as possible
for (; len >= WORD_SIZE; len -= WORD_SIZE) {
assembly {
mstore(dest, mload(src))
}
src += WORD_SIZE;
dest += WORD_SIZE;
}
// left over bytes. Mask is used to remove unwanted bytes from the word
uint mask = 256 ** (WORD_SIZE - len) - 1;
assembly {
let srcpart := and(mload(src), not(mask)) // zero out src
let destpart := and(mload(dest), mask) // retrieve the bytes
mstore(dest, or(destpart, srcpart))
}
}
}
\ No newline at end of file
packages/contracts/build/contracts/libraries/rlp/Lib_RLPWriter.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/**
* Source: https://github.com/omisego/plasma-mvp/blob/master/plasma/root_chain/contracts/RLPEncode.sol
* @title RLPEncode
* @dev A simple RLP encoding library.
* @author Bakaoh
*/
library Lib_RLPWriter {
/*
* Public Functions
*/
/**
* RLP encodes a byte string.
* @param self The byte string to encode.
* @return The RLP encoded string in bytes.
*/
function encodeBytes(
bytes memory self
)
internal
pure
returns (bytes memory)
{
bytes memory encoded;
if (self.length == 1 && uint8(self[0]) < 128) {
encoded = self;
} else {
encoded = concat(encodeLength(self.length, 128), self);
}
return encoded;
}
/**
* RLP encodes a list of RLP encoded byte byte strings.
* @param self The list of RLP encoded byte strings.
* @return The RLP encoded list of items in bytes.
*/
function encodeList(
bytes[] memory self
)
internal
pure
returns (bytes memory)
{
bytes memory list = flatten(self);
return concat(encodeLength(list.length, 192), list);
}
/**
* RLP encodes a string.
* @param self The string to encode.
* @return The RLP encoded string in bytes.
*/
function encodeString(
string memory self
)
internal
pure
returns (bytes memory)
{
return encodeBytes(bytes(self));
}
/**
* RLP encodes an address.
* @param self The address to encode.
* @return The RLP encoded address in bytes.
*/
function encodeAddress(
address self
)
internal
pure
returns (bytes memory)
{
bytes memory inputBytes;
assembly {
let m := mload(0x40)
mstore(add(m, 20), xor(0x140000000000000000000000000000000000000000, self))
mstore(0x40, add(m, 52))
inputBytes := m
}
return encodeBytes(inputBytes);
}
/**
* RLP encodes a uint.
* @param self The uint to encode.
* @return The RLP encoded uint in bytes.
*/
function encodeUint(
uint self
)
internal
pure
returns (bytes memory)
{
return encodeBytes(toBinary(self));
}
/**
* RLP encodes an int.
* @param self The int to encode.
* @return The RLP encoded int in bytes.
*/
function encodeInt(
int self
)
internal
pure
returns (bytes memory)
{
return encodeUint(uint(self));
}
/**
* RLP encodes a bool.
* @param self The bool to encode.
* @return The RLP encoded bool in bytes.
*/
function encodeBool(
bool self
)
internal
pure
returns (bytes memory)
{
bytes memory encoded = new bytes(1);
encoded[0] = (self ? bytes1(0x01) : bytes1(0x80));
return encoded;
}
/*
* Private Functions
*/
/**
* Encode the first byte, followed by the `len` in binary form if `length` is more than 55.
* @param len The length of the string or the payload.
* @param offset 128 if item is string, 192 if item is list.
* @return RLP encoded bytes.
*/
function encodeLength(
uint len,
uint offset
)
private
pure
returns (bytes memory)
{
bytes memory encoded;
if (len < 56) {
encoded = new bytes(1);
encoded[0] = byte(uint8(len) + uint8(offset));
} else {
uint lenLen;
uint i = 1;
while (len / i != 0) {
lenLen++;
i *= 256;
}
encoded = new bytes(lenLen + 1);
encoded[0] = byte(uint8(lenLen) + uint8(offset) + 55);
for(i = 1; i <= lenLen; i++) {
encoded[i] = byte(uint8((len / (256**(lenLen-i))) % 256));
}
}
return encoded;
}
/**
* Encode integer in big endian binary form with no leading zeroes.
* @notice TODO: This should be optimized with assembly to save gas costs.
* @param _x The integer to encode.
* @return RLP encoded bytes.
*/
function toBinary(
uint _x
)
private
pure
returns (bytes memory)
{
bytes memory b = new bytes(32);
assembly {
mstore(add(b, 32), _x)
}
uint i = 0;
for (; i < 32; i++) {
if (b[i] != 0) {
break;
}
}
bytes memory res = new bytes(32 - i);
for (uint j = 0; j < res.length; j++) {
res[j] = b[i++];
}
return res;
}
/**
* Copies a piece of memory to another location.
* @notice From: https://github.com/Arachnid/solidity-stringutils/blob/master/src/strings.sol.
* @param _dest Destination location.
* @param _src Source location.
* @param _len Length of memory to copy.
*/
function memcpy(
uint _dest,
uint _src,
uint _len
)
private
pure
{
uint dest = _dest;
uint src = _src;
uint len = _len;
for(; len >= 32; len -= 32) {
assembly {
mstore(dest, mload(src))
}
dest += 32;
src += 32;
}
uint mask = 256 ** (32 - len) - 1;
assembly {
let srcpart := and(mload(src), not(mask))
let destpart := and(mload(dest), mask)
mstore(dest, or(destpart, srcpart))
}
}
/**
* Flattens a list of byte strings into one byte string.
* @notice From: https://github.com/sammayo/solidity-rlp-encoder/blob/master/RLPEncode.sol.
* @param _list List of byte strings to flatten.
* @return The flattened byte string.
*/
function flatten(
bytes[] memory _list
)
private
pure
returns (bytes memory)
{
if (_list.length == 0) {
return new bytes(0);
}
uint len;
uint i = 0;
for (; i < _list.length; i++) {
len += _list[i].length;
}
bytes memory flattened = new bytes(len);
uint flattenedPtr;
assembly { flattenedPtr := add(flattened, 0x20) }
for(i = 0; i < _list.length; i++) {
bytes memory item = _list[i];
uint listPtr;
assembly { listPtr := add(item, 0x20)}
memcpy(flattenedPtr, listPtr, item.length);
flattenedPtr += _list[i].length;
}
return flattened;
}
/**
* Concatenates two bytes.
* @notice From: https://github.com/GNSPS/solidity-bytes-utils/blob/master/contracts/BytesLib.sol.
* @param _preBytes First byte string.
* @param _postBytes Second byte string.
* @return Both byte string combined.
*/
function concat(
bytes memory _preBytes,
bytes memory _postBytes
)
private
pure
returns (bytes memory)
{
bytes memory tempBytes;
assembly {
tempBytes := mload(0x40)
let length := mload(_preBytes)
mstore(tempBytes, length)
let mc := add(tempBytes, 0x20)
let end := add(mc, length)
for {
let cc := add(_preBytes, 0x20)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
length := mload(_postBytes)
mstore(tempBytes, add(length, mload(tempBytes)))
mc := end
end := add(mc, length)
for {
let cc := add(_postBytes, 0x20)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
mstore(0x40, and(
add(add(end, iszero(add(length, mload(_preBytes)))), 31),
not(31)
))
}
return tempBytes;
}
}
\ No newline at end of file
packages/contracts/build/contracts/libraries/trie/Lib_EthMerkleTrie.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_SecureMerkleTrie } from "./Lib_SecureMerkleTrie.sol";
import { Lib_OVMCodec } from "../codec/Lib_OVMCodec.sol";
import { Lib_ByteUtils } from "../utils/Lib_ByteUtils.sol";
import { Lib_RLPWriter } from "../rlp/Lib_RLPWriter.sol";
import { Lib_RLPReader } from "../rlp/Lib_RLPReader.sol";
/**
* @title Lib_EthMerkleTrie
*/
library Lib_EthMerkleTrie {
/**********************
* Contract Constants *
**********************/
bytes constant private RLP_NULL_BYTES = hex'80';
bytes32 constant private BYTES32_NULL = bytes32('');
uint256 constant private UINT256_NULL = uint256(0);
/*************************************
* Internal Functions: Storage Slots *
*************************************/
/**
* @notice Verifies a proof for the value of an account storage slot.
* @param _address Address of the contract account.
* @param _key Key for the storage slot.
* @param _value Value for the storage slot.
* @param _stateTrieWitness Inclusion proof for the account state within
* the state trie.
* @param _storageTrieWitness Inclusion proof for the specific storage
* slot associated with the given key.
* @param _stateTrieRoot Known root of the state trie.
* @return `true` if the k/v pair is included, `false` otherwise.
*/
function proveAccountStorageSlotValue(
address _address,
bytes32 _key,
bytes32 _value,
bytes memory _stateTrieWitness,
bytes memory _storageTrieWitness,
bytes32 _stateTrieRoot
)
internal
view
returns (bool)
{
// Retrieve the current storage root.
Lib_OVMCodec.EVMAccount memory accountState = getAccountState(
_address,
_stateTrieWitness,
_stateTrieRoot
);
// Verify inclusion of the given k/v pair in the storage trie.
return Lib_SecureMerkleTrie.verifyInclusionProof(
abi.encodePacked(_key),
abi.encodePacked(_value),
_storageTrieWitness,
accountState.storageRoot
);
}
/**
* @notice Updates the value for a given account storage slot.
* @param _address Address of the contract account.
* @param _key Key for the storage slot.
* @param _value New value for the storage slot.
* @param _stateTrieWitness Inclusion proof for the account state within
* the state trie.
* @param _storageTrieWitness Inclusion proof for the specific storage
* slot associated with the given key.
* @param _stateTrieRoot Known root of the state trie.
* @return Root hash of the updated state trie.
*/
function updateAccountStorageSlotValue(
address _address,
bytes32 _key,
bytes32 _value,
bytes memory _stateTrieWitness,
bytes memory _storageTrieWitness,
bytes32 _stateTrieRoot
)
internal
view
returns (bytes32)
{
// Retreive the old storage root.
Lib_OVMCodec.EVMAccount memory accountState = getAccountState(
_address,
_stateTrieWitness,
_stateTrieRoot
);
// Generate a new storage root.
accountState.storageRoot = Lib_SecureMerkleTrie.update(
abi.encodePacked(_key),
abi.encodePacked(_value),
_storageTrieWitness,
accountState.storageRoot
);
// Update the state trie with the new storage root.
return setAccountState(
accountState,
_address,
_stateTrieWitness,
_stateTrieRoot
);
}
/**************************************
* Internal Functions: Account Proofs *
*************************************/
/**
* @notice Verifies a proof of the current state for a given account.
* @param _address Address of the target account.
* @param _accountState Account state object to verify.
* @param _proofMatrix Matrix of fields to verify or ignore.
* @param _stateTrieWitness Inclusion proof for the account state within
* the state trie.
* @param _stateTrieRoot Known root of the state trie.
* @return `true` if the given account state is valid, `false` otherwise.
*/
function proveAccountState(
address _address,
Lib_OVMCodec.EVMAccount memory _accountState,
Lib_OVMCodec.ProofMatrix memory _proofMatrix,
bytes memory _stateTrieWitness,
bytes32 _stateTrieRoot
)
internal
view
returns (bool)
{
// Pull the current account state.
Lib_OVMCodec.EVMAccount memory accountState = getAccountState(
_address,
_stateTrieWitness,
_stateTrieRoot
);
// Check each provided component conditionally.
return (
(!_proofMatrix.checkNonce || accountState.nonce == _accountState.nonce) &&
(!_proofMatrix.checkBalance || accountState.balance == _accountState.balance) &&
(!_proofMatrix.checkStorageRoot || accountState.storageRoot == _accountState.storageRoot) &&
(!_proofMatrix.checkCodeHash || accountState.codeHash == _accountState.codeHash)
);
}
/**
* @notice Verifies a proof of the current state for a given account.
* @param _address Address of the target account.
* @param _accountState Account state object to verify.
* @param _stateTrieWitness Inclusion proof for the account state within
* the state trie.
* @param _stateTrieRoot Known root of the state trie.
* @return `true` if the given account state is valid, `false` otherwise.
*/
function proveAccountState(
address _address,
Lib_OVMCodec.EVMAccount memory _accountState,
bytes memory _stateTrieWitness,
bytes32 _stateTrieRoot
)
internal
view
returns (bool)
{
return proveAccountState(
_address,
_accountState,
Lib_OVMCodec.ProofMatrix({
checkNonce: true,
checkBalance: true,
checkStorageRoot: true,
checkCodeHash: true
}),
_stateTrieWitness,
_stateTrieRoot
);
}
/**
* @notice Verifies a proof of the current state for a given account.
* @param _address Address of the target account.
* @param _accountState Account state object to verify.
* @param _stateTrieWitness Inclusion proof for the account state within
* the state trie.
* @param _stateTrieRoot Known root of the state trie.
* @return `true` if the given account state is valid, `false` otherwise.
*/
function proveAccountState(
address _address,
Lib_OVMCodec.Account memory _accountState,
bytes memory _stateTrieWitness,
bytes32 _stateTrieRoot
)
internal
view
returns (bool)
{
return proveAccountState(
_address,
Lib_OVMCodec.EVMAccount({
nonce: _accountState.nonce,
balance: _accountState.balance,
storageRoot: _accountState.storageRoot,
codeHash: _accountState.codeHash
}),
_stateTrieWitness,
_stateTrieRoot
);
}
/**
* @notice Verifies a proof of the account nonce.
* @param _address Address of the target account.
* @param _nonce Account transaction nonce.
* @param _stateTrieWitness Inclusion proof for the account state within
* the state trie.
* @param _stateTrieRoot Known root of the state trie.
* @return `true` if the given nonce is valid, `false` otherwise.
*/
function proveAccountNonce(
address _address,
uint256 _nonce,
bytes memory _stateTrieWitness,
bytes32 _stateTrieRoot
)
internal
view
returns (bool)
{
return proveAccountState(
_address,
Lib_OVMCodec.EVMAccount({
nonce: _nonce,
balance: UINT256_NULL,
storageRoot: BYTES32_NULL,
codeHash: BYTES32_NULL
}),
Lib_OVMCodec.ProofMatrix({
checkNonce: true,
checkBalance: false,
checkStorageRoot: false,
checkCodeHash: false
}),
_stateTrieWitness,
_stateTrieRoot
);
}
/**
* @notice Verifies a proof of the account balance.
* @param _address Address of the target account.
* @param _balance Account balance in wei.
* @param _stateTrieWitness Inclusion proof for the account state within
* the state trie.
* @param _stateTrieRoot Known root of the state trie.
* @return `true` if the given balance is valid, `false` otherwise.
*/
function proveAccountBalance(
address _address,
uint256 _balance,
bytes memory _stateTrieWitness,
bytes32 _stateTrieRoot
)
internal
view
returns (bool)
{
return proveAccountState(
_address,
Lib_OVMCodec.EVMAccount({
nonce: UINT256_NULL,
balance: _balance,
storageRoot: BYTES32_NULL,
codeHash: BYTES32_NULL
}),
Lib_OVMCodec.ProofMatrix({
checkNonce: false,
checkBalance: true,
checkStorageRoot: false,
checkCodeHash: false
}),
_stateTrieWitness,
_stateTrieRoot
);
}
/**
* @notice Verifies a proof of the account storage root.
* @param _address Address of the target account.
* @param _storageRoot Account storage root, empty if EOA.
* @param _stateTrieWitness Inclusion proof for the account state within
* the state trie.
* @param _stateTrieRoot Known root of the state trie.
* @return `true` if the given storage root is valid, `false` otherwise.
*/
function proveAccountStorageRoot(
address _address,
bytes32 _storageRoot,
bytes memory _stateTrieWitness,
bytes32 _stateTrieRoot
)
internal
view
returns (bool)
{
return proveAccountState(
_address,
Lib_OVMCodec.EVMAccount({
nonce: UINT256_NULL,
balance: UINT256_NULL,
storageRoot: _storageRoot,
codeHash: BYTES32_NULL
}),
Lib_OVMCodec.ProofMatrix({
checkNonce: false,
checkBalance: false,
checkStorageRoot: true,
checkCodeHash: false
}),
_stateTrieWitness,
_stateTrieRoot
);
}
/**
* @notice Verifies a proof of the account code hash.
* @param _address Address of the target account.
* @param _codeHash Account code hash, empty if EOA.
* @param _stateTrieWitness Inclusion proof for the account state within
* the state trie.
* @param _stateTrieRoot Known root of the state trie.
* @return `true` if the given code hash is valid, `false` otherwise.
*/
function proveAccountCodeHash(
address _address,
bytes32 _codeHash,
bytes memory _stateTrieWitness,
bytes32 _stateTrieRoot
)
internal
view
returns (bool)
{
return proveAccountState(
_address,
Lib_OVMCodec.EVMAccount({
nonce: UINT256_NULL,
balance: UINT256_NULL,
storageRoot: BYTES32_NULL,
codeHash: _codeHash
}),
Lib_OVMCodec.ProofMatrix({
checkNonce: false,
checkBalance: false,
checkStorageRoot: false,
checkCodeHash: true
}),
_stateTrieWitness,
_stateTrieRoot
);
}
/***************************************
* Internal Functions: Account Updates *
***************************************/
/**
* @notice Updates the current state for a given account.
* @param _address Address of the target account.
* @param _accountState Account state to insert.
* @param _proofMatrix Matrix of fields to update or ignore.
* @param _stateTrieWitness Inclusion proof for the account state within
* the state trie.
* @param _stateTrieRoot Known root of the state trie.
* @return Root hash of the updated state trie.
*/
function updateAccountState(
address _address,
Lib_OVMCodec.EVMAccount memory _accountState,
Lib_OVMCodec.ProofMatrix memory _proofMatrix,
bytes memory _stateTrieWitness,
bytes32 _stateTrieRoot
)
internal
view
returns (bytes32)
{
Lib_OVMCodec.EVMAccount memory newAccountState = _accountState;
// If the user has provided everything, don't bother pulling the
// current account state.
if (
!_proofMatrix.checkNonce ||
!_proofMatrix.checkBalance ||
!_proofMatrix.checkStorageRoot ||
!_proofMatrix.checkCodeHash
) {
// Pull the old account state.
Lib_OVMCodec.EVMAccount memory oldAccountState = getAccountState(
_address,
_stateTrieWitness,
_stateTrieRoot
);
// Conditionally update elements that haven't been provided with
// elements from the old account state.
if (!_proofMatrix.checkNonce) {
newAccountState.nonce = oldAccountState.nonce;
}
if (!_proofMatrix.checkBalance) {
newAccountState.balance = oldAccountState.balance;
}
if (!_proofMatrix.checkStorageRoot) {
newAccountState.storageRoot = oldAccountState.storageRoot;
}
if (!_proofMatrix.checkCodeHash) {
newAccountState.codeHash = oldAccountState.codeHash;
}
}
// Update the account state.
return setAccountState(
newAccountState,
_address,
_stateTrieWitness,
_stateTrieRoot
);
}
/**
* @notice Updates the current state for a given account.
* @param _address Address of the target account.
* @param _accountState Account state to insert.
* @param _stateTrieWitness Inclusion proof for the account state within
* the state trie.
* @param _stateTrieRoot Known root of the state trie.
* @return Root hash of the updated state trie.
*/
function updateAccountState(
address _address,
Lib_OVMCodec.EVMAccount memory _accountState,
bytes memory _stateTrieWitness,
bytes32 _stateTrieRoot
)
internal
view
returns (bytes32)
{
return updateAccountState(
_address,
_accountState,
Lib_OVMCodec.ProofMatrix({
checkNonce: true,
checkBalance: true,
checkStorageRoot: true,
checkCodeHash: true
}),
_stateTrieWitness,
_stateTrieRoot
);
}
/**
* @notice Updates the current state for a given account.
* @param _address Address of the target account.
* @param _accountState Account state to insert.
* @param _stateTrieWitness Inclusion proof for the account state within
* the state trie.
* @param _stateTrieRoot Known root of the state trie.
* @return Root hash of the updated state trie.
*/
function updateAccountState(
address _address,
Lib_OVMCodec.Account memory _accountState,
bytes memory _stateTrieWitness,
bytes32 _stateTrieRoot
)
internal
view
returns (bytes32)
{
return updateAccountState(
_address,
Lib_OVMCodec.EVMAccount({
nonce: _accountState.nonce,
balance: _accountState.balance,
storageRoot: _accountState.storageRoot,
codeHash: _accountState.codeHash
}),
_stateTrieWitness,
_stateTrieRoot
);
}
/**
* @notice Updates an account nonce.
* @param _address Address of the target account.
* @param _nonce New account transaction nonce.
* @param _stateTrieWitness Inclusion proof for the account state within
* the state trie.
* @param _stateTrieRoot Known root of the state trie.
* @return Root hash of the updated state trie.
*/
function updateAccountNonce(
address _address,
uint256 _nonce,
bytes memory _stateTrieWitness,
bytes32 _stateTrieRoot
)
internal
view
returns (bytes32)
{
return updateAccountState(
_address,
Lib_OVMCodec.EVMAccount({
nonce: _nonce,
balance: UINT256_NULL,
storageRoot: BYTES32_NULL,
codeHash: BYTES32_NULL
}),
Lib_OVMCodec.ProofMatrix({
checkNonce: true,
checkBalance: false,
checkStorageRoot: false,
checkCodeHash: false
}),
_stateTrieWitness,
_stateTrieRoot
);
}
/**
* @notice Updates an account balance.
* @param _address Address of the target account.
* @param _balance New account balance in wei.
* @param _stateTrieWitness Inclusion proof for the account state within
* the state trie.
* @param _stateTrieRoot Known root of the state trie.
* @return Root hash of the updated state trie.
*/
function updateAccountBalance(
address _address,
uint256 _balance,
bytes memory _stateTrieWitness,
bytes32 _stateTrieRoot
)
internal
view
returns (bytes32)
{
return updateAccountState(
_address,
Lib_OVMCodec.EVMAccount({
nonce: UINT256_NULL,
balance: _balance,
storageRoot: BYTES32_NULL,
codeHash: BYTES32_NULL
}),
Lib_OVMCodec.ProofMatrix({
checkNonce: false,
checkBalance: true,
checkStorageRoot: false,
checkCodeHash: false
}),
_stateTrieWitness,
_stateTrieRoot
);
}
/**
* @notice Updates an account storage root.
* @param _address Address of the target account.
* @param _storageRoot New account storage root, empty if EOA.
* @param _stateTrieWitness Inclusion proof for the account state within
* the state trie.
* @param _stateTrieRoot Known root of the state trie.
* @return Root hash of the updated state trie.
*/
function updateAccountStorageRoot(
address _address,
bytes32 _storageRoot,
bytes memory _stateTrieWitness,
bytes32 _stateTrieRoot
)
internal
view
returns (bytes32)
{
return updateAccountState(
_address,
Lib_OVMCodec.EVMAccount({
nonce: UINT256_NULL,
balance: UINT256_NULL,
storageRoot: _storageRoot,
codeHash: BYTES32_NULL
}),
Lib_OVMCodec.ProofMatrix({
checkNonce: false,
checkBalance: false,
checkStorageRoot: true,
checkCodeHash: false
}),
_stateTrieWitness,
_stateTrieRoot
);
}
/**
* @notice Updates an account code hash.
* @param _address Address of the target account.
* @param _codeHash New account code hash, empty if EOA.
* @param _stateTrieWitness Inclusion proof for the account state within
* the state trie.
* @param _stateTrieRoot Known root of the state trie.
* @return Root hash of the updated state trie.
*/
function updateAccountCodeHash(
address _address,
bytes32 _codeHash,
bytes memory _stateTrieWitness,
bytes32 _stateTrieRoot
)
internal
view
returns (bytes32)
{
return updateAccountState(
_address,
Lib_OVMCodec.EVMAccount({
nonce: UINT256_NULL,
balance: UINT256_NULL,
storageRoot: BYTES32_NULL,
codeHash: _codeHash
}),
Lib_OVMCodec.ProofMatrix({
checkNonce: false,
checkBalance: false,
checkStorageRoot: false,
checkCodeHash: true
}),
_stateTrieWitness,
_stateTrieRoot
);
}
/*********************
* Private Functions *
*********************/
/**
* @notice Decodes an RLP-encoded account state into a useful struct.
* @param _encodedAccountState RLP-encoded account state.
* @return Account state struct.
*/
function decodeAccountState(
bytes memory _encodedAccountState
)
private
view
returns (Lib_OVMCodec.EVMAccount memory)
{
Lib_RLPReader.RLPItem[] memory accountState = Lib_RLPReader.toList(Lib_RLPReader.toRlpItem(_encodedAccountState));
return Lib_OVMCodec.EVMAccount({
nonce: Lib_RLPReader.toUint(accountState[0]),
balance: Lib_RLPReader.toUint(accountState[1]),
storageRoot: Lib_ByteUtils.toBytes32(Lib_RLPReader.toBytes(accountState[2])),
codeHash: Lib_ByteUtils.toBytes32(Lib_RLPReader.toBytes(accountState[3]))
});
}
/**
* @notice RLP-encodes an account state struct.
* @param _accountState Account state struct.
* @return RLP-encoded account state.
*/
function encodeAccountState(
Lib_OVMCodec.EVMAccount memory _accountState
)
private
view
returns (bytes memory)
{
bytes[] memory raw = new bytes[](4);
// Unfortunately we can't create this array outright because
// RLPWriter.encodeList will reject fixed-size arrays. Assigning
// index-by-index circumvents this issue.
raw[0] = Lib_RLPWriter.encodeUint(_accountState.nonce);
raw[1] = Lib_RLPWriter.encodeUint(_accountState.balance);
raw[2] = _accountState.storageRoot == 0 ? RLP_NULL_BYTES : Lib_RLPWriter.encodeBytes(abi.encodePacked(_accountState.storageRoot));
raw[3] = _accountState.codeHash == 0 ? RLP_NULL_BYTES : Lib_RLPWriter.encodeBytes(abi.encodePacked(_accountState.codeHash));
return Lib_RLPWriter.encodeList(raw);
}
/**
* @notice Retrieves the current account state and converts into a struct.
* @param _address Account address.
* @param _stateTrieWitness Inclusion proof for the account state within
* the state trie.
* @param _stateTrieRoot Known root of the state trie.
*/
function getAccountState(
address _address,
bytes memory _stateTrieWitness,
bytes32 _stateTrieRoot
)
private
view
returns (Lib_OVMCodec.EVMAccount memory)
{
Lib_OVMCodec.EVMAccount memory DEFAULT_ACCOUNT_STATE = Lib_OVMCodec.EVMAccount({
nonce: UINT256_NULL,
balance: UINT256_NULL,
storageRoot: keccak256(hex'80'),
codeHash: keccak256(hex'')
});
(
bool exists,
bytes memory encodedAccountState
) = Lib_SecureMerkleTrie.get(
abi.encodePacked(_address),
_stateTrieWitness,
_stateTrieRoot
);
return exists ? decodeAccountState(encodedAccountState) : DEFAULT_ACCOUNT_STATE;
}
/**
* @notice Updates the current account state for a given address.
* @param _accountState New account state, as a struct.
* @param _address Account address.
* @param _stateTrieWitness Inclusion proof for the account state within
* the state trie.
* @param _stateTrieRoot Known root of the state trie.
* @return Root hash of the updated state trie.
*/
function setAccountState(
Lib_OVMCodec.EVMAccount memory _accountState,
address _address,
bytes memory _stateTrieWitness,
bytes32 _stateTrieRoot
)
private
view
returns (bytes32)
{
bytes memory encodedAccountState = encodeAccountState(_accountState);
return Lib_SecureMerkleTrie.update(
abi.encodePacked(_address),
encodedAccountState,
_stateTrieWitness,
_stateTrieRoot
);
}
}
\ No newline at end of file
packages/contracts/build/contracts/libraries/trie/Lib_MerkleTrie.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/* Library Imports */
import { Lib_ByteUtils } from "../utils/Lib_ByteUtils.sol";
import { Lib_RLPReader } from "../rlp/Lib_RLPReader.sol";
import { Lib_RLPWriter } from "../rlp/Lib_RLPWriter.sol";
/**
* @title Lib_MerkleTrie
*/
library Lib_MerkleTrie {
/*******************
* Data Structures *
*******************/
enum NodeType {
BranchNode,
ExtensionNode,
LeafNode
}
struct TrieNode {
bytes encoded;
Lib_RLPReader.RLPItem[] decoded;
}
/**********************
* Contract Constants *
**********************/
// TREE_RADIX determines the number of elements per branch node.
uint256 constant TREE_RADIX = 16;
// Branch nodes have TREE_RADIX elements plus an additional `value` slot.
uint256 constant BRANCH_NODE_LENGTH = TREE_RADIX + 1;
// Leaf nodes and extension nodes always have two elements, a `path` and a `value`.
uint256 constant LEAF_OR_EXTENSION_NODE_LENGTH = 2;
// Prefixes are prepended to the `path` within a leaf or extension node and
// allow us to differentiate between the two node types. `ODD` or `EVEN` is
// determined by the number of nibbles within the unprefixed `path`. If the
// number of nibbles if even, we need to insert an extra padding nibble so
// the resulting prefixed `path` has an even number of nibbles.
uint8 constant PREFIX_EXTENSION_EVEN = 0;
uint8 constant PREFIX_EXTENSION_ODD = 1;
uint8 constant PREFIX_LEAF_EVEN = 2;
uint8 constant PREFIX_LEAF_ODD = 3;
// Just a utility constant. RLP represents `NULL` as 0x80.
bytes1 constant RLP_NULL = bytes1(0x80);
bytes constant RLP_NULL_BYTES = hex'80';
/**********************
* Internal Functions *
**********************/
/**
* @notice Verifies a proof that a given key/value pair is present in the
* Merkle trie.
* @param _key Key of the node to search for, as a hex string.
* @param _value Value of the node to search for, as a hex string.
* @param _proof Merkle trie inclusion proof for the desired node. Unlike
* traditional Merkle trees, this proof is executed top-down and consists
* of a list of RLP-encoded nodes that make a path down to the target node.
* @param _root Known root of the Merkle trie. Used to verify that the
* included proof is correctly constructed.
* @return `true` if the k/v pair exists in the trie, `false` otherwise.
*/
function verifyInclusionProof(
bytes memory _key,
bytes memory _value,
bytes memory _proof,
bytes32 _root
)
internal
view
returns (
bool
)
{
return _verifyProof(_key, _value, _proof, _root, true);
}
/**
* @notice Verifies a proof that a given key/value pair is *not* present in
* the Merkle trie.
* @param _key Key of the node to search for, as a hex string.
* @param _value Value of the node to search for, as a hex string.
* @param _proof Merkle trie inclusion proof for the node *nearest* the
* target node. We effectively need to show that either the key exists and
* its value differs, or the key does not exist at all.
* @param _root Known root of the Merkle trie. Used to verify that the
* included proof is correctly constructed.
* @return `true` if the k/v pair is absent in the trie, `false` otherwise.
*/
function verifyExclusionProof(
bytes memory _key,
bytes memory _value,
bytes memory _proof,
bytes32 _root
)
internal
view
returns (
bool
)
{
return _verifyProof(_key, _value, _proof, _root, false);
}
/**
* @notice Updates a Merkle trie and returns a new root hash.
* @param _key Key of the node to update, as a hex string.
* @param _value Value of the node to update, as a hex string.
* @param _proof Merkle trie inclusion proof for the node *nearest* the
* target node. If the key exists, we can simply update the value.
* Otherwise, we need to modify the trie to handle the new k/v pair.
* @param _root Known root of the Merkle trie. Used to verify that the
* included proof is correctly constructed.
* @return Root hash of the newly constructed trie.
*/
function update(
bytes memory _key,
bytes memory _value,
bytes memory _proof,
bytes32 _root
)
internal
view
returns (
bytes32
)
{
TrieNode[] memory proof = _parseProof(_proof);
(uint256 pathLength, bytes memory keyRemainder, ) = _walkNodePath(proof, _key, _root);
TrieNode[] memory newPath = _getNewPath(proof, pathLength, keyRemainder, _value);
return _getUpdatedTrieRoot(newPath, _key);
}
/**
* @notice Retrieves the value associated with a given key.
* @param _key Key to search for, as hex bytes.
* @param _proof Merkle trie inclusion proof for the key.
* @param _root Known root of the Merkle trie.
* @return Whether the node exists, value associated with the key if so.
*/
function get(
bytes memory _key,
bytes memory _proof,
bytes32 _root
)
internal
view
returns (
bool,
bytes memory
)
{
TrieNode[] memory proof = _parseProof(_proof);
(uint256 pathLength, bytes memory keyRemainder, ) = _walkNodePath(proof, _key, _root);
bool exists = keyRemainder.length == 0;
bytes memory value = exists ? _getNodeValue(proof[pathLength - 1]) : bytes('');
return (
exists,
value
);
}
/**
* Computes the root hash for a trie with a single node.
* @param _key Key for the single node.
* @param _value Value for the single node.
* @return Hash of the trie.
*/
function getSingleNodeRootHash(
bytes memory _key,
bytes memory _value
)
internal
view
returns (
bytes32
)
{
return keccak256(_makeLeafNode(
_key,
_value
).encoded);
}
/*********************
* Private Functions *
*********************/
/**
* @notice Utility function that handles verification of inclusion or
* exclusion proofs. Since the verification methods are almost identical,
* it's easier to shove this into a single function.
* @param _key Key of the node to search for, as a hex string.
* @param _value Value of the node to search for, as a hex string.
* @param _proof Merkle trie inclusion proof for the node *nearest* the
* target node. If we're proving explicit inclusion, the nearest node
* should be the target node.
* @param _root Known root of the Merkle trie. Used to verify that the
* included proof is correctly constructed.
* @param _inclusion Whether to check for inclusion or exclusion.
* @return `true` if the k/v pair is (in/not in) the trie, `false` otherwise.
*/
function _verifyProof(
bytes memory _key,
bytes memory _value,
bytes memory _proof,
bytes32 _root,
bool _inclusion
)
private
view
returns (
bool
)
{
TrieNode[] memory proof = _parseProof(_proof);
(uint256 pathLength, bytes memory keyRemainder, bool isFinalNode) = _walkNodePath(proof, _key, _root);
if (_inclusion) {
// Included leaf nodes should have no key remainder, values should match.
return (
keyRemainder.length == 0 &&
Lib_ByteUtils.equal(_getNodeValue(proof[pathLength - 1]), _value)
);
} else {
// If there's no key remainder then a leaf with the given key exists and the value should differ.
// Otherwise, we need to make sure that we've hit a dead end.
return (
(keyRemainder.length == 0 && !Lib_ByteUtils.equal(_getNodeValue(proof[pathLength - 1]), _value)) ||
(keyRemainder.length != 0 && isFinalNode)
);
}
}
/**
* @notice Walks through a proof using a provided key.
* @param _proof Inclusion proof to walk through.
* @param _key Key to use for the walk.
* @param _root Known root of the trie.
* @return (
* Length of the final path;
* Portion of the key remaining after the walk;
* Whether or not we've hit a dead end;
* )
*/
function _walkNodePath(
TrieNode[] memory _proof,
bytes memory _key,
bytes32 _root
)
private
view
returns (
uint256,
bytes memory,
bool
)
{
uint256 pathLength = 0;
bytes memory key = Lib_ByteUtils.toNibbles(_key);
bytes32 currentNodeID = _root;
uint256 currentKeyIndex = 0;
uint256 currentKeyIncrement = 0;
TrieNode memory currentNode;
// Proof is top-down, so we start at the first element (root).
for (uint256 i = 0; i < _proof.length; i++) {
currentNode = _proof[i];
currentKeyIndex += currentKeyIncrement;
// Keep track of the proof elements we actually need.
// It's expensive to resize arrays, so this simply reduces gas costs.
pathLength += 1;
if (currentKeyIndex == 0) {
// First proof element is always the root node.
require(
keccak256(currentNode.encoded) == currentNodeID,
"Invalid root hash"
);
} else if (currentNode.encoded.length >= 32) {
// Nodes 32 bytes or larger are hashed inside branch nodes.
require(
keccak256(currentNode.encoded) == currentNodeID,
"Invalid large internal hash"
);
} else {
// Nodes smaller than 31 bytes aren't hashed.
require(
Lib_ByteUtils.toBytes32(currentNode.encoded) == currentNodeID,
"Invalid internal node hash"
);
}
if (currentNode.decoded.length == BRANCH_NODE_LENGTH) {
if (currentKeyIndex == key.length) {
// We've hit the end of the key, meaning the value should be within this branch node.
break;
} else {
// We're not at the end of the key yet.
// Figure out what the next node ID should be and continue.
uint8 branchKey = uint8(key[currentKeyIndex]);
Lib_RLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey];
currentNodeID = _getNodeID(nextNode);
currentKeyIncrement = 1;
continue;
}
} else if (currentNode.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) {
bytes memory path = _getNodePath(currentNode);
uint8 prefix = uint8(path[0]);
uint8 offset = 2 - prefix % 2;
bytes memory pathRemainder = Lib_ByteUtils.slice(path, offset);
bytes memory keyRemainder = Lib_ByteUtils.slice(key, currentKeyIndex);
uint256 sharedNibbleLength = _getSharedNibbleLength(pathRemainder, keyRemainder);
if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) {
if (
pathRemainder.length == sharedNibbleLength &&
keyRemainder.length == sharedNibbleLength
) {
// The key within this leaf matches our key exactly.
// Increment the key index to reflect that we have no remainder.
currentKeyIndex += sharedNibbleLength;
}
// We've hit a leaf node, so our next node should be NULL.
currentNodeID = bytes32(RLP_NULL);
break;
} else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) {
if (sharedNibbleLength == 0) {
// Our extension node doesn't share any part of our key.
// We've hit the end of this path, updates will need to modify this extension.
currentNodeID = bytes32(RLP_NULL);
break;
} else {
// Our extension shares some nibbles.
// Carry on to the next node.
currentNodeID = _getNodeID(currentNode.decoded[1]);
currentKeyIncrement = sharedNibbleLength;
continue;
}
}
}
}
// If our node ID is NULL, then we're at a dead end.
bool isFinalNode = currentNodeID == bytes32(RLP_NULL);
return (pathLength, Lib_ByteUtils.slice(key, currentKeyIndex), isFinalNode);
}
/**
* @notice Creates new nodes to support a k/v pair insertion into a given
* Merkle trie path.
* @param _path Path to the node nearest the k/v pair.
* @param _pathLength Length of the path. Necessary because the provided
* path may include additional nodes (e.g., it comes directly from a proof)
* and we can't resize in-memory arrays without costly duplication.
* @param _keyRemainder Portion of the initial key that must be inserted
* into the trie.
* @param _value Value to insert at the given key.
* @return A new path with the inserted k/v pair and extra supporting nodes.
*/
function _getNewPath(
TrieNode[] memory _path,
uint256 _pathLength,
bytes memory _keyRemainder,
bytes memory _value
)
private
view
returns (
TrieNode[] memory
)
{
bytes memory keyRemainder = _keyRemainder;
// Most of our logic depends on the status of the last node in the path.
TrieNode memory lastNode = _path[_pathLength - 1];
NodeType lastNodeType = _getNodeType(lastNode);
// Create an array for newly created nodes.
// We need up to three new nodes, depending on the contents of the last node.
// Since array resizing is expensive, we'll keep track of the size manually.
// We're using an explicit `totalNewNodes += 1` after insertions for clarity.
TrieNode[] memory newNodes = new TrieNode[](3);
uint256 totalNewNodes = 0;
if (keyRemainder.length == 0 && lastNodeType == NodeType.LeafNode) {
// We've found a leaf node with the given key.
// Simply need to update the value of the node to match.
newNodes[totalNewNodes] = _makeLeafNode(_getNodeKey(lastNode), _value);
totalNewNodes += 1;
} else if (lastNodeType == NodeType.BranchNode) {
if (keyRemainder.length == 0) {
// We've found a branch node with the given key.
// Simply need to update the value of the node to match.
newNodes[totalNewNodes] = _editBranchValue(lastNode, _value);
totalNewNodes += 1;
} else {
// We've found a branch node, but it doesn't contain our key.
// Reinsert the old branch for now.
newNodes[totalNewNodes] = lastNode;
totalNewNodes += 1;
// Create a new leaf node, slicing our remainder since the first byte points
// to our branch node.
newNodes[totalNewNodes] = _makeLeafNode(Lib_ByteUtils.slice(keyRemainder, 1), _value);
totalNewNodes += 1;
}
} else {
// Our last node is either an extension node or a leaf node with a different key.
bytes memory lastNodeKey = _getNodeKey(lastNode);
uint256 sharedNibbleLength = _getSharedNibbleLength(lastNodeKey, keyRemainder);
if (sharedNibbleLength != 0) {
// We've got some shared nibbles between the last node and our key remainder.
// We'll need to insert an extension node that covers these shared nibbles.
bytes memory nextNodeKey = Lib_ByteUtils.slice(lastNodeKey, 0, sharedNibbleLength);
newNodes[totalNewNodes] = _makeExtensionNode(nextNodeKey, _getNodeHash(_value));
totalNewNodes += 1;
// Cut down the keys since we've just covered these shared nibbles.
lastNodeKey = Lib_ByteUtils.slice(lastNodeKey, sharedNibbleLength);
keyRemainder = Lib_ByteUtils.slice(keyRemainder, sharedNibbleLength);
}
// Create an empty branch to fill in.
TrieNode memory newBranch = _makeEmptyBranchNode();
if (lastNodeKey.length == 0) {
// Key remainder was larger than the key for our last node.
// The value within our last node is therefore going to be shifted into
// a branch value slot.
newBranch = _editBranchValue(newBranch, _getNodeValue(lastNode));
} else {
// Last node key was larger than the key remainder.
// We're going to modify some index of our branch.
uint8 branchKey = uint8(lastNodeKey[0]);
// Move on to the next nibble.
lastNodeKey = Lib_ByteUtils.slice(lastNodeKey, 1);
if (lastNodeType == NodeType.LeafNode) {
// We're dealing with a leaf node.
// We'll modify the key and insert the old leaf node into the branch index.
TrieNode memory modifiedLastNode = _makeLeafNode(lastNodeKey, _getNodeValue(lastNode));
newBranch = _editBranchIndex(newBranch, branchKey, _getNodeHash(modifiedLastNode.encoded));
} else if (lastNodeKey.length != 0) {
// We're dealing with a shrinking extension node.
// We need to modify the node to decrease the size of the key.
TrieNode memory modifiedLastNode = _makeExtensionNode(lastNodeKey, _getNodeValue(lastNode));
newBranch = _editBranchIndex(newBranch, branchKey, _getNodeHash(modifiedLastNode.encoded));
} else {
// We're dealing with an unnecessary extension node.
// We're going to delete the node entirely.
// Simply insert its current value into the branch index.
newBranch = _editBranchIndex(newBranch, branchKey, _getNodeValue(lastNode));
}
}
if (keyRemainder.length == 0) {
// We've got nothing left in the key remainder.
// Simply insert the value into the branch value slot.
newBranch = _editBranchValue(newBranch, _value);
// Push the branch into the list of new nodes.
newNodes[totalNewNodes] = newBranch;
totalNewNodes += 1;
} else {
// We've got some key remainder to work with.
// We'll be inserting a leaf node into the trie.
// First, move on to the next nibble.
keyRemainder = Lib_ByteUtils.slice(keyRemainder, 1);
// Push the branch into the list of new nodes.
newNodes[totalNewNodes] = newBranch;
totalNewNodes += 1;
// Push a new leaf node for our k/v pair.
newNodes[totalNewNodes] = _makeLeafNode(keyRemainder, _value);
totalNewNodes += 1;
}
}
// Finally, join the old path with our newly created nodes.
// Since we're overwriting the last node in the path, we use `_pathLength - 1`.
return _joinNodeArrays(_path, _pathLength - 1, newNodes, totalNewNodes);
}
/**
* @notice Computes the trie root from a given path.
* @param _nodes Path to some k/v pair.
* @param _key Key for the k/v pair.
* @return Root hash for the updated trie.
*/
function _getUpdatedTrieRoot(
TrieNode[] memory _nodes,
bytes memory _key
)
private
view
returns (
bytes32
)
{
bytes memory key = Lib_ByteUtils.toNibbles(_key);
// Some variables to keep track of during iteration.
TrieNode memory currentNode;
NodeType currentNodeType;
bytes memory previousNodeHash;
// Run through the path backwards to rebuild our root hash.
for (uint256 i = _nodes.length; i > 0; i--) {
// Pick out the current node.
currentNode = _nodes[i - 1];
currentNodeType = _getNodeType(currentNode);
if (currentNodeType == NodeType.LeafNode) {
// Leaf nodes are already correctly encoded.
// Shift the key over to account for the nodes key.
bytes memory nodeKey = _getNodeKey(currentNode);
key = Lib_ByteUtils.slice(key, 0, key.length - nodeKey.length);
} else if (currentNodeType == NodeType.ExtensionNode) {
// Shift the key over to account for the nodes key.
bytes memory nodeKey = _getNodeKey(currentNode);
key = Lib_ByteUtils.slice(key, 0, key.length - nodeKey.length);
// If this node is the last element in the path, it'll be correctly encoded
// and we can skip this part.
if (previousNodeHash.length > 0) {
// Re-encode the node based on the previous node.
currentNode = _makeExtensionNode(nodeKey, previousNodeHash);
}
} else if (currentNodeType == NodeType.BranchNode) {
// If this node is the last element in the path, it'll be correctly encoded
// and we can skip this part.
if (previousNodeHash.length > 0) {
// Re-encode the node based on the previous node.
uint8 branchKey = uint8(key[key.length - 1]);
key = Lib_ByteUtils.slice(key, 0, key.length - 1);
currentNode = _editBranchIndex(currentNode, branchKey, previousNodeHash);
}
}
// Compute the node hash for the next iteration.
previousNodeHash = _getNodeHash(currentNode.encoded);
}
// Current node should be the root at this point.
// Simply return the hash of its encoding.
return keccak256(currentNode.encoded);
}
/**
* @notice Parses an RLP-encoded proof into something more useful.
* @param _proof RLP-encoded proof to parse.
* @return Proof parsed into easily accessible structs.
*/
function _parseProof(
bytes memory _proof
)
private
view
returns (
TrieNode[] memory
)
{
Lib_RLPReader.RLPItem[] memory nodes = Lib_RLPReader.toList(Lib_RLPReader.toRlpItem(_proof));
TrieNode[] memory proof = new TrieNode[](nodes.length);
for (uint256 i = 0; i < nodes.length; i++) {
bytes memory encoded = Lib_RLPReader.toBytes(nodes[i]);
proof[i] = TrieNode({
encoded: encoded,
decoded: Lib_RLPReader.toList(Lib_RLPReader.toRlpItem(encoded))
});
}
return proof;
}
/**
* @notice Picks out the ID for a node. Node ID is referred to as the
* "hash" within the specification, but nodes < 32 bytes are not actually
* hashed.
* @param _node Node to pull an ID for.
* @return ID for the node, depending on the size of its contents.
*/
function _getNodeID(
Lib_RLPReader.RLPItem memory _node
)
private
view
returns (
bytes32
)
{
bytes memory nodeID;
if (_node.len < 32) {
// Nodes smaller than 32 bytes are RLP encoded.
nodeID = Lib_RLPReader.toRlpBytes(_node);
} else {
// Nodes 32 bytes or larger are hashed.
nodeID = Lib_RLPReader.toBytes(_node);
}
return Lib_ByteUtils.toBytes32(nodeID);
}
/**
* @notice Gets the path for a leaf or extension node.
* @param _node Node to get a path for.
* @return Node path, converted to an array of nibbles.
*/
function _getNodePath(
TrieNode memory _node
)
private
view
returns (
bytes memory
)
{
return Lib_ByteUtils.toNibbles(Lib_RLPReader.toBytes(_node.decoded[0]));
}
/**
* @notice Gets the key for a leaf or extension node. Keys are essentially
* just paths without any prefix.
* @param _node Node to get a key for.
* @return Node key, converted to an array of nibbles.
*/
function _getNodeKey(
TrieNode memory _node
)
private
view
returns (
bytes memory
)
{
return _removeHexPrefix(_getNodePath(_node));
}
/**
* @notice Gets the path for a node.
* @param _node Node to get a value for.
* @return Node value, as hex bytes.
*/
function _getNodeValue(
TrieNode memory _node
)
private
view
returns (
bytes memory
)
{
return Lib_RLPReader.toBytes(_node.decoded[_node.decoded.length - 1]);
}
/**
* @notice Computes the node hash for an encoded node. Nodes < 32 bytes
* are not hashed, all others are keccak256 hashed.
* @param _encoded Encoded node to hash.
* @return Hash of the encoded node. Simply the input if < 32 bytes.
*/
function _getNodeHash(
bytes memory _encoded
)
private
pure
returns (
bytes memory
)
{
if (_encoded.length < 32) {
return _encoded;
} else {
return abi.encodePacked(keccak256(_encoded));
}
}
/**
* @notice Determines the type for a given node.
* @param _node Node to determine a type for.
* @return Type of the node; BranchNode/ExtensionNode/LeafNode.
*/
function _getNodeType(
TrieNode memory _node
)
private
view
returns (
NodeType
)
{
if (_node.decoded.length == BRANCH_NODE_LENGTH) {
return NodeType.BranchNode;
} else if (_node.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) {
bytes memory path = _getNodePath(_node);
uint8 prefix = uint8(path[0]);
if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) {
return NodeType.LeafNode;
} else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) {
return NodeType.ExtensionNode;
}
}
revert("Invalid node type");
}
/**
* @notice Utility; determines the number of nibbles shared between two
* nibble arrays.
* @param _a First nibble array.
* @param _b Second nibble array.
* @return Number of shared nibbles.
*/
function _getSharedNibbleLength(
bytes memory _a,
bytes memory _b
)
private
view
returns (
uint256
)
{
uint256 i = 0;
while (_a.length > i && _b.length > i && _a[i] == _b[i]) {
i++;
}
return i;
}
/**
* @notice Utility; converts an RLP-encoded node into our nice struct.
* @param _raw RLP-encoded node to convert.
* @return Node as a TrieNode struct.
*/
function _makeNode(
bytes[] memory _raw
)
private
view
returns (
TrieNode memory
)
{
bytes memory encoded = Lib_RLPWriter.encodeList(_raw);
return TrieNode({
encoded: encoded,
decoded: Lib_RLPReader.toList(Lib_RLPReader.toRlpItem(encoded))
});
}
/**
* @notice Utility; converts an RLP-decoded node into our nice struct.
* @param _items RLP-decoded node to convert.
* @return Node as a TrieNode struct.
*/
function _makeNode(
Lib_RLPReader.RLPItem[] memory _items
)
private
view
returns (
TrieNode memory
)
{
bytes[] memory raw = new bytes[](_items.length);
for (uint256 i = 0; i < _items.length; i++) {
raw[i] = Lib_RLPReader.toRlpBytes(_items[i]);
}
return _makeNode(raw);
}
/**
* @notice Creates a new extension node.
* @param _key Key for the extension node, unprefixed.
* @param _value Value for the extension node.
* @return New extension node with the given k/v pair.
*/
function _makeExtensionNode(
bytes memory _key,
bytes memory _value
)
private
view
returns (
TrieNode memory
)
{
bytes[] memory raw = new bytes[](2);
bytes memory key = _addHexPrefix(_key, false);
raw[0] = Lib_RLPWriter.encodeBytes(Lib_ByteUtils.fromNibbles(key));
raw[1] = Lib_RLPWriter.encodeBytes(_value);
return _makeNode(raw);
}
/**
* @notice Creates a new leaf node.
* @dev This function is essentially identical to `_makeExtensionNode`.
* Although we could route both to a single method with a flag, it's
* more gas efficient to keep them separate and duplicate the logic.
* @param _key Key for the leaf node, unprefixed.
* @param _value Value for the leaf node.
* @return New leaf node with the given k/v pair.
*/
function _makeLeafNode(
bytes memory _key,
bytes memory _value
)
private
view
returns (
TrieNode memory
)
{
bytes[] memory raw = new bytes[](2);
bytes memory key = _addHexPrefix(_key, true);
raw[0] = Lib_RLPWriter.encodeBytes(Lib_ByteUtils.fromNibbles(key));
raw[1] = Lib_RLPWriter.encodeBytes(_value);
return _makeNode(raw);
}
/**
* @notice Creates an empty branch node.
* @return Empty branch node as a TrieNode stuct.
*/
function _makeEmptyBranchNode()
private
view
returns (
TrieNode memory
)
{
bytes[] memory raw = new bytes[](BRANCH_NODE_LENGTH);
for (uint256 i = 0; i < raw.length; i++) {
raw[i] = RLP_NULL_BYTES;
}
return _makeNode(raw);
}
/**
* @notice Modifies the value slot for a given branch.
* @param _branch Branch node to modify.
* @param _value Value to insert into the branch.
* @return Modified branch node.
*/
function _editBranchValue(
TrieNode memory _branch,
bytes memory _value
)
private
view
returns (
TrieNode memory
)
{
bytes memory encoded = Lib_RLPWriter.encodeBytes(_value);
_branch.decoded[_branch.decoded.length - 1] = Lib_RLPReader.toRlpItem(encoded);
return _makeNode(_branch.decoded);
}
/**
* @notice Modifies a slot at an index for a given branch.
* @param _branch Branch node to modify.
* @param _index Slot index to modify.
* @param _value Value to insert into the slot.
* @return Modified branch node.
*/
function _editBranchIndex(
TrieNode memory _branch,
uint8 _index,
bytes memory _value
)
private
view
returns (
TrieNode memory
)
{
bytes memory encoded = _value.length < 32 ? _value : Lib_RLPWriter.encodeBytes(_value);
_branch.decoded[_index] = Lib_RLPReader.toRlpItem(encoded);
return _makeNode(_branch.decoded);
}
/**
* @notice Utility; adds a prefix to a key.
* @param _key Key to prefix.
* @param _isLeaf Whether or not the key belongs to a leaf.
* @return Prefixed key.
*/
function _addHexPrefix(
bytes memory _key,
bool _isLeaf
)
private
view
returns (
bytes memory
)
{
uint8 prefix = _isLeaf ? uint8(0x02) : uint8(0x00);
uint8 offset = uint8(_key.length % 2);
bytes memory prefixed = new bytes(2 - offset);
prefixed[0] = bytes1(prefix + offset);
return Lib_ByteUtils.concat(prefixed, _key);
}
/**
* @notice Utility; removes a prefix from a path.
* @param _path Path to remove the prefix from.
* @return Unprefixed key.
*/
function _removeHexPrefix(
bytes memory _path
)
private
view
returns (
bytes memory
)
{
if (uint8(_path[0]) % 2 == 0) {
return Lib_ByteUtils.slice(_path, 2);
} else {
return Lib_ByteUtils.slice(_path, 1);
}
}
/**
* @notice Utility; combines two node arrays. Array lengths are required
* because the actual lengths may be longer than the filled lengths.
* Array resizing is extremely costly and should be avoided.
* @param _a First array to join.
* @param _aLength Length of the first array.
* @param _b Second array to join.
* @param _bLength Length of the second array.
* @return Combined node array.
*/
function _joinNodeArrays(
TrieNode[] memory _a,
uint256 _aLength,
TrieNode[] memory _b,
uint256 _bLength
)
private
pure
returns (
TrieNode[] memory
)
{
TrieNode[] memory ret = new TrieNode[](_aLength + _bLength);
// Copy elements from the first array.
for (uint256 i = 0; i < _aLength; i++) {
ret[i] = _a[i];
}
// Copy elements from the second array.
for (uint256 i = 0; i < _bLength; i++) {
ret[i + _aLength] = _b[i];
}
return ret;
}
}
packages/contracts/build/contracts/libraries/trie/Lib_SecureMerkleTrie.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_MerkleTrie } from "./Lib_MerkleTrie.sol";
/**
* @title Lib_SecureMerkleTrie
*/
library Lib_SecureMerkleTrie {
/**********************
* Internal Functions *
**********************/
/**
* @notice Verifies a proof that a given key/value pair is present in the
* Merkle trie.
* @param _key Key of the node to search for, as a hex string.
* @param _value Value of the node to search for, as a hex string.
* @param _proof Merkle trie inclusion proof for the desired node. Unlike
* traditional Merkle trees, this proof is executed top-down and consists
* of a list of RLP-encoded nodes that make a path down to the target node.
* @param _root Known root of the Merkle trie. Used to verify that the
* included proof is correctly constructed.
* @return `true` if the k/v pair exists in the trie, `false` otherwise.
*/
function verifyInclusionProof(
bytes memory _key,
bytes memory _value,
bytes memory _proof,
bytes32 _root
)
internal
view
returns (
bool
)
{
bytes memory key = _getSecureKey(_key);
return Lib_MerkleTrie.verifyInclusionProof(key, _value, _proof, _root);
}
/**
* @notice Verifies a proof that a given key/value pair is *not* present in
* the Merkle trie.
* @param _key Key of the node to search for, as a hex string.
* @param _value Value of the node to search for, as a hex string.
* @param _proof Merkle trie inclusion proof for the node *nearest* the
* target node. We effectively need to show that either the key exists and
* its value differs, or the key does not exist at all.
* @param _root Known root of the Merkle trie. Used to verify that the
* included proof is correctly constructed.
* @return `true` if the k/v pair is absent in the trie, `false` otherwise.
*/
function verifyExclusionProof(
bytes memory _key,
bytes memory _value,
bytes memory _proof,
bytes32 _root
)
internal
view
returns (
bool
)
{
bytes memory key = _getSecureKey(_key);
return Lib_MerkleTrie.verifyExclusionProof(key, _value, _proof, _root);
}
/**
* @notice Updates a Merkle trie and returns a new root hash.
* @param _key Key of the node to update, as a hex string.
* @param _value Value of the node to update, as a hex string.
* @param _proof Merkle trie inclusion proof for the node *nearest* the
* target node. If the key exists, we can simply update the value.
* Otherwise, we need to modify the trie to handle the new k/v pair.
* @param _root Known root of the Merkle trie. Used to verify that the
* included proof is correctly constructed.
* @return Root hash of the newly constructed trie.
*/
function update(
bytes memory _key,
bytes memory _value,
bytes memory _proof,
bytes32 _root
)
internal
view
returns (
bytes32
)
{
bytes memory key = _getSecureKey(_key);
return Lib_MerkleTrie.update(key, _value, _proof, _root);
}
/**
* @notice Retrieves the value associated with a given key.
* @param _key Key to search for, as hex bytes.
* @param _proof Merkle trie inclusion proof for the key.
* @param _root Known root of the Merkle trie.
* @return Whether the node exists, value associated with the key if so.
*/
function get(
bytes memory _key,
bytes memory _proof,
bytes32 _root
)
internal
view
returns (
bool,
bytes memory
)
{
bytes memory key = _getSecureKey(_key);
return Lib_MerkleTrie.get(key, _proof, _root);
}
/**
* Computes the root hash for a trie with a single node.
* @param _key Key for the single node.
* @param _value Value for the single node.
* @return Hash of the trie.
*/
function getSingleNodeRootHash(
bytes memory _key,
bytes memory _value
)
internal
view
returns (
bytes32
)
{
bytes memory key = _getSecureKey(_key);
return Lib_MerkleTrie.getSingleNodeRootHash(key, _value);
}
/*********************
* Private Functions *
*********************/
function _getSecureKey(
bytes memory _key
)
private
pure
returns (
bytes memory
)
{
return abi.encodePacked(keccak256(_key));
}
}
\ No newline at end of file
packages/contracts/build/contracts/libraries/utils/Lib_ByteUtils.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/**
* @title Lib_ByteUtils
*/
library Lib_ByteUtils {
/**********************
* Internal Functions *
**********************/
function concat(
bytes memory _preBytes,
bytes memory _postBytes
)
internal
pure
returns (bytes memory)
{
bytes memory tempBytes;
assembly {
// Get a location of some free memory and store it in tempBytes as
// Solidity does for memory variables.
tempBytes := mload(0x40)
// Store the length of the first bytes array at the beginning of
// the memory for tempBytes.
let length := mload(_preBytes)
mstore(tempBytes, length)
// Maintain a memory counter for the current write location in the
// temp bytes array by adding the 32 bytes for the array length to
// the starting location.
let mc := add(tempBytes, 0x20)
// Stop copying when the memory counter reaches the length of the
// first bytes array.
let end := add(mc, length)
for {
// Initialize a copy counter to the start of the _preBytes data,
// 32 bytes into its memory.
let cc := add(_preBytes, 0x20)
} lt(mc, end) {
// Increase both counters by 32 bytes each iteration.
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
// Write the _preBytes data into the tempBytes memory 32 bytes
// at a time.
mstore(mc, mload(cc))
}
// Add the length of _postBytes to the current length of tempBytes
// and store it as the new length in the first 32 bytes of the
// tempBytes memory.
length := mload(_postBytes)
mstore(tempBytes, add(length, mload(tempBytes)))
// Move the memory counter back from a multiple of 0x20 to the
// actual end of the _preBytes data.
mc := end
// Stop copying when the memory counter reaches the new combined
// length of the arrays.
end := add(mc, length)
for {
let cc := add(_postBytes, 0x20)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
// Update the free-memory pointer by padding our last write location
// to 32 bytes: add 31 bytes to the end of tempBytes to move to the
// next 32 byte block, then round down to the nearest multiple of
// 32. If the sum of the length of the two arrays is zero then add
// one before rounding down to leave a blank 32 bytes (the length block with 0).
mstore(0x40, and(
add(add(end, iszero(add(length, mload(_preBytes)))), 31),
not(31) // Round down to the nearest 32 bytes.
))
}
return tempBytes;
}
function slice(
bytes memory _bytes,
uint256 _start,
uint256 _length
)
internal
pure
returns (bytes memory)
{
require(_bytes.length >= (_start + _length), "Read out of bounds");
bytes memory tempBytes;
assembly {
switch iszero(_length)
case 0 {
// Get a location of some free memory and store it in tempBytes as
// Solidity does for memory variables.
tempBytes := mload(0x40)
// The first word of the slice result is potentially a partial
// word read from the original array. To read it, we calculate
// the length of that partial word and start copying that many
// bytes into the array. The first word we copy will start with
// data we don't care about, but the last `lengthmod` bytes will
// land at the beginning of the contents of the new array. When
// we're done copying, we overwrite the full first word with
// the actual length of the slice.
let lengthmod := and(_length, 31)
// The multiplication in the next line is necessary
// because when slicing multiples of 32 bytes (lengthmod == 0)
// the following copy loop was copying the origin's length
// and then ending prematurely not copying everything it should.
let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
let end := add(mc, _length)
for {
// The multiplication in the next line has the same exact purpose
// as the one above.
let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
mstore(tempBytes, _length)
//update free-memory pointer
//allocating the array padded to 32 bytes like the compiler does now
mstore(0x40, and(add(mc, 31), not(31)))
}
//if we want a zero-length slice let's just return a zero-length array
default {
tempBytes := mload(0x40)
mstore(0x40, add(tempBytes, 0x20))
}
}
return tempBytes;
}
function slice(
bytes memory _bytes,
uint256 _start
)
internal
pure
returns (bytes memory)
{
if (_bytes.length - _start == 0) {
return bytes('');
}
return slice(_bytes, _start, _bytes.length - _start);
}
function toBytes32(
bytes memory _bytes
)
internal
pure
returns (bytes32)
{
bytes32 ret;
assembly {
ret := mload(add(_bytes, 32))
}
return ret;
}
function toUint256(
bytes memory _bytes
)
internal
pure
returns (uint256)
{
return uint256(toBytes32(_bytes));
}
function toNibbles(
bytes memory _bytes
)
internal
pure
returns (bytes memory)
{
bytes memory nibbles = new bytes(_bytes.length * 2);
for (uint256 i = 0; i < _bytes.length; i++) {
nibbles[i * 2] = _bytes[i] >> 4;
nibbles[i * 2 + 1] = bytes1(uint8(_bytes[i]) % 16);
}
return nibbles;
}
function fromNibbles(
bytes memory _bytes
)
internal
pure
returns (bytes memory)
{
bytes memory ret = new bytes(_bytes.length / 2);
for (uint256 i = 0; i < ret.length; i++) {
ret[i] = (_bytes[i * 2] << 4) | (_bytes[i * 2 + 1]);
}
return ret;
}
function equal(
bytes memory _bytes,
bytes memory _other
)
internal
pure
returns (bool)
{
return keccak256(_bytes) == keccak256(_other);
}
}
packages/contracts/build/contracts/libraries/utils/Lib_Bytes32Utils.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/**
* @title Lib_Byte32Utils
*/
library Lib_Bytes32Utils {
/**********************
* Internal Functions *
**********************/
function toBool(
bytes32 _in
)
internal
pure
returns (
bool _out
)
{
return _in != 0;
}
function fromBool(
bool _in
)
internal
pure
returns (
bytes32 _out
)
{
return bytes32(uint256(_in ? 1 : 0));
}
function toAddress(
bytes32 _in
)
internal
pure
returns (
address _out
)
{
return address(uint160(uint256(_in)));
}
function fromAddress(
address _in
)
internal
pure
returns (
bytes32 _out
)
{
return bytes32(bytes20(_in));
}
}
packages/contracts/build/contracts/libraries/utils/Lib_ECDSAUtils.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/**
* @title Lib_ECDSAUtils
*/
library Lib_ECDSAUtils {
/**************************************
* Internal Functions: ECDSA Recovery *
**************************************/
/**
* Recovers a signed address given a message and signature.
* @param _message Message that was originally signed.
* @param _isEthSignedMessage Whether or not the user used the `Ethereum Signed Message` prefix.
* @param _v Signature `v` parameter.
* @param _r Signature `r` parameter.
* @param _s Signature `s` parameter.
* @param _chainId Chain ID parameter.
* @return _sender Signer address.
*/
function recover(
bytes memory _message,
bool _isEthSignedMessage,
uint8 _v,
bytes32 _r,
bytes32 _s,
uint256 _chainId
)
internal
pure
returns (
address _sender
)
{
bytes32 messageHash;
if (_isEthSignedMessage) {
messageHash = getEthSignedMessageHash(_message);
} else {
messageHash = getNativeMessageHash(_message);
}
return ecrecover(
messageHash,
(_v - uint8(_chainId) * 2) - 8,
_r,
_s
);
}
/*************************************
* Private Functions: ECDSA Recovery *
*************************************/
/**
* Gets the native message hash (simple keccak256) for a message.
* @param _message Message to hash.
* @return _messageHash Native message hash.
*/
function getNativeMessageHash(
bytes memory _message
)
private
pure
returns (
bytes32 _messageHash
)
{
return keccak256(_message);
}
/**
* Gets the hash of a message with the `Ethereum Signed Message` prefix.
* @param _message Message to hash.
* @return _messageHash Prefixed message hash.
*/
function getEthSignedMessageHash(
bytes memory _message
)
private
pure
returns (
bytes32 _messageHash
)
{
bytes memory prefix = "\x19Ethereum Signed Message:\n32";
bytes32 messageHash = keccak256(_message);
return keccak256(abi.encodePacked(prefix, messageHash));
}
}
\ No newline at end of file
packages/contracts/build/contracts/libraries/utils/Lib_EthUtils.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_RLPWriter } from "../rlp/Lib_RLPWriter.sol";
/**
* @title Lib_EthUtils
*/
library Lib_EthUtils {
/***********************************
* Internal Functions: Code Access *
***********************************/
/**
* Gets the code for a given address.
* @param _address Address to get code for.
* @param _offset Offset to start reading from.
* @param _length Number of bytes to read.
* @return _code Code read from the contract.
*/
function getCode(
address _address,
uint256 _offset,
uint256 _length
)
internal
view
returns (
bytes memory _code
)
{
assembly {
_code := mload(0x40)
mstore(0x40, add(_code, add(_length, 0x20)))
mstore(_code, _length)
extcodecopy(_address, add(_code, 0x20), _offset, _length)
}
return _code;
}
/**
* Gets the full code for a given address.
* @param _address Address to get code for.
* @return _code Full code of the contract.
*/
function getCode(
address _address
)
internal
view
returns (
bytes memory _code
)
{
return getCode(
_address,
0,
getCodeSize(_address)
);
}
/**
* Gets the size of a contract's code in bytes.
* @param _address Address to get code size for.
* @return _codeSize Size of the contract's code in bytes.
*/
function getCodeSize(
address _address
)
internal
view
returns (
uint256 _codeSize
)
{
assembly {
_codeSize := extcodesize(_address)
}
return _codeSize;
}
/**
* Gets the hash of a contract's code.
* @param _address Address to get a code hash for.
* @return _codeHash Hash of the contract's code.
*/
function getCodeHash(
address _address
)
internal
view
returns (
bytes32 _codeHash
)
{
assembly {
_codeHash := extcodehash(_address)
}
return _codeHash;
}
/*****************************************
* Internal Functions: Contract Creation *
*****************************************/
/**
* Creates a contract with some given initialization code.
* @param _code Contract initialization code.
* @return _created Address of the created contract.
*/
function createContract(
bytes memory _code
)
internal
returns (
address _created
)
{
assembly {
_created := create(
0,
add(_code, 0x20),
mload(_code)
)
}
return _created;
}
/**
* Computes the address that would be generated by CREATE.
* @param _creator Address creating the contract.
* @param _nonce Creator's nonce.
* @return _address Address to be generated by CREATE.
*/
function getAddressForCREATE(
address _creator,
uint256 _nonce
)
internal
view
returns (
address _address
)
{
bytes[] memory encoded = new bytes[](2);
encoded[0] = Lib_RLPWriter.encodeAddress(_creator);
encoded[1] = Lib_RLPWriter.encodeUint(_nonce);
bytes memory encodedList = Lib_RLPWriter.encodeList(encoded);
return getAddressFromHash(keccak256(encodedList));
}
/**
* Computes the address that would be generated by CREATE2.
* @param _creator Address creating the contract.
* @param _bytecode Bytecode of the contract to be created.
* @param _salt 32 byte salt value mixed into the hash.
* @return _address Address to be generated by CREATE2.
*/
function getAddressForCREATE2(
address _creator,
bytes memory _bytecode,
bytes32 _salt
)
internal
view
returns (address _address)
{
bytes32 hashedData = keccak256(abi.encodePacked(
byte(0xff),
_creator,
_salt,
keccak256(_bytecode)
));
return getAddressFromHash(hashedData);
}
/****************************************
* Private Functions: Contract Creation *
****************************************/
/**
* Determines an address from a 32 byte hash. Since addresses are only
* 20 bytes, we need to retrieve the last 20 bytes from the original
* hash. Converting to uint256 and then uint160 gives us these bytes.
* @param _hash Hash to convert to an address.
* @return _address Hash converted to an address.
*/
function getAddressFromHash(
bytes32 _hash
)
private
pure
returns (
address _address
)
{
return address(bytes20(uint160(uint256(_hash))));
}
}
packages/contracts/build/contracts/libraries/utils/Lib_MerkleUtils.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/**
* @title Lib_MerkleUtils
*/
library Lib_MerkleUtils {
function getMerkleRoot(
bytes32[] memory _hashes
)
internal
view
returns (
bytes32 _root
)
{
if (_hashes.length == 1) {
return _hashes[0];
}
bytes32[] memory defaultHashes = _getDefaultHashes(_hashes.length);
bytes32[] memory nodes = _hashes;
if (_hashes.length % 2 == 1) {
nodes = new bytes32[](_hashes.length + 1);
for (uint256 i = 0; i < _hashes.length; i++) {
nodes[i] = _hashes[i];
}
}
uint256 currentLevel = 0;
uint256 nextLevelSize = _hashes.length;
if (nextLevelSize % 2 == 1) {
nodes[nextLevelSize] = defaultHashes[currentLevel];
nextLevelSize += 1;
}
while (nextLevelSize > 1) {
currentLevel += 1;
for (uint256 i = 0; i < nextLevelSize / 2; i++) {
nodes[i] = _getParentHash(
nodes[i*2],
nodes[i*2 + 1]
);
}
nextLevelSize = nextLevelSize / 2;
if (nextLevelSize % 2 == 1 && nextLevelSize != 1) {
nodes[nextLevelSize] = defaultHashes[currentLevel];
nextLevelSize += 1;
}
}
return nodes[0];
}
function getMerkleRoot(
bytes[] memory _elements
)
internal
view
returns (
bytes32 _root
)
{
bytes32[] memory hashes = new bytes32[](_elements.length);
for (uint256 i = 0; i < _elements.length; i++) {
hashes[i] = keccak256(_elements[i]);
}
return getMerkleRoot(hashes);
}
function verify(
bytes32 _root,
bytes memory _leaf,
uint256 _path,
bytes32[] memory _siblings
)
internal
pure
returns (
bool _verified
)
{
bytes32 computedRoot = keccak256(_leaf);
for (uint256 i = 0; i < _siblings.length; i++) {
bytes32 sibling = _siblings[i];
bool isRightSibling = uint8(_path >> i & 1) == 1;
if (isRightSibling) {
computedRoot = _getParentHash(computedRoot, sibling);
} else {
computedRoot = _getParentHash(sibling, computedRoot);
}
}
return computedRoot == _root;
}
function _getDefaultHashes(
uint256 _length
)
private
pure
returns (
bytes32[] memory _defaultHashes
)
{
bytes32[] memory defaultHashes = new bytes32[](_length);
defaultHashes[0] = keccak256(abi.encodePacked(uint256(0)));
for (uint256 i = 1; i < defaultHashes.length; i++) {
defaultHashes[i] = keccak256(abi.encodePacked(defaultHashes[i-1]));
}
return defaultHashes;
}
function _getParentHash(
bytes32 _leftChildHash,
bytes32 _rightChildHash
)
private
pure
returns (
bytes32 _hash
)
{
return keccak256(abi.encodePacked(_leftChildHash, _rightChildHash));
}
}
\ No newline at end of file
packages/contracts/build/contracts/mockOVM/bridge/mockOVM_CrossDomainMessenger.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Contract Imports */
import { OVM_BaseCrossDomainMessenger } from "../../OVM/bridge/OVM_BaseCrossDomainMessenger.sol";
/**
* @title mockOVM_CrossDomainMessenger
*/
contract mockOVM_CrossDomainMessenger is OVM_BaseCrossDomainMessenger {
/***********
* Structs *
***********/
struct ReceivedMessage {
uint256 timestamp;
address target;
address sender;
bytes message;
uint256 messageNonce;
uint256 gasLimit;
}
/**********************
* Contract Variables *
**********************/
ReceivedMessage[] internal fullReceivedMessages;
uint256 internal lastRelayedMessage;
uint256 internal delay;
/***************
* Constructor *
***************/
/**
* @param _delay Time in seconds before a message can be relayed.
*/
constructor(
uint256 _delay
) {
delay = _delay;
}
/********************
* Public Functions *
********************/
/**
* Sends a message to another mock xdomain messenger.
* @param _target Target for the message.
* @param _message Message to send.
* @param _gasLimit Amount of gas to send with the call.
*/
function sendMessage(
address _target,
bytes memory _message,
uint32 _gasLimit
)
public
{
mockOVM_CrossDomainMessenger targetMessenger = mockOVM_CrossDomainMessenger(
targetMessengerAddress
);
// Just send it over!
targetMessenger.receiveMessage(ReceivedMessage({
timestamp: block.timestamp,
target: _target,
sender: msg.sender,
message: _message,
messageNonce: messageNonce,
gasLimit: _gasLimit
}));
messageNonce += 1;
}
/**
* Receives a message to be sent later.
* @param _message Message to send later.
*/
function receiveMessage(
ReceivedMessage memory _message
)
public
{
fullReceivedMessages.push(_message);
}
/**
* Checks whether we have messages to relay.
* @param _exists Whether or not we have more messages to relay.
*/
function hasNextMessage()
public
view
returns (
bool _exists
)
{
return fullReceivedMessages.length < lastRelayedMessage;
}
/**
* Relays the last received message not yet relayed.
*/
function relayNextMessage()
public
{
if (hasNextMessage() == false) {
return;
}
ReceivedMessage memory nextMessage = fullReceivedMessages[lastRelayedMessage];
if (nextMessage.timestamp + delay > block.timestamp) {
return;
}
xDomainMessageSender = nextMessage.sender;
nextMessage.target.call{gas: nextMessage.gasLimit}(nextMessage.message);
lastRelayedMessage += 1;
}
}
packages/contracts/
contracts/optimistic-ethereum
/proxy/Proxy_Forwarder.sol
→
packages/contracts/
build/contracts
/proxy/Proxy_Forwarder.sol
View file @
6e1dbfe0
File moved
packages/contracts/
contracts/optimistic-ethereum
/proxy/Proxy_Manager.sol
→
packages/contracts/
build/contracts
/proxy/Proxy_Manager.sol
View file @
6e1dbfe0
File moved
packages/contracts/
contracts/optimistic-ethereum
/proxy/Proxy_Resolver.sol
→
packages/contracts/
build/contracts
/proxy/Proxy_Resolver.sol
View file @
6e1dbfe0
File moved
packages/contracts/build/test/helpers/buidler/modify-compiler.d.ts
0 → 100644
View file @
6e1dbfe0
export
{};
packages/contracts/build/test/helpers/buidler/modify-compiler.js
0 → 100644
View file @
6e1dbfe0
"
use strict
"
;
var
__importDefault
=
(
this
&&
this
.
__importDefault
)
||
function
(
mod
)
{
return
(
mod
&&
mod
.
__esModule
)
?
mod
:
{
"
default
"
:
mod
};
};
Object
.
defineProperty
(
exports
,
"
__esModule
"
,
{
value
:
true
});
const
fs_extra_1
=
__importDefault
(
require
(
"
fs-extra
"
));
const
config_1
=
require
(
"
@nomiclabs/buidler/config
"
);
const
strings_1
=
require
(
"
@nomiclabs/buidler/internal/util/strings
"
);
const
artifacts_1
=
require
(
"
@nomiclabs/buidler/internal/artifacts
"
);
const
task_names_1
=
require
(
"
@nomiclabs/buidler/builtin-tasks/task-names
"
);
config_1
.
internalTask
(
task_names_1
.
TASK_COMPILE_GET_COMPILER_INPUT
,
async
(
_
,
{
config
,
run
},
runSuper
)
=>
{
const
input
=
await
runSuper
();
input
.
settings
.
outputSelection
[
'
*
'
][
'
*
'
].
push
(
'
storageLayout
'
);
return
input
;
});
config_1
.
internalTask
(
task_names_1
.
TASK_BUILD_ARTIFACTS
).
setAction
(
async
({
force
},
{
config
,
run
})
=>
{
const
sources
=
await
run
(
task_names_1
.
TASK_COMPILE_GET_SOURCE_PATHS
);
if
(
sources
.
length
===
0
)
{
console
.
log
(
'
No Solidity source file available.
'
);
return
;
}
const
isCached
=
await
run
(
task_names_1
.
TASK_COMPILE_CHECK_CACHE
,
{
force
});
if
(
isCached
)
{
console
.
log
(
'
All contracts have already been compiled, skipping compilation.
'
);
return
;
}
const
compilationOutput
=
await
run
(
task_names_1
.
TASK_COMPILE_COMPILE
);
if
(
compilationOutput
===
undefined
)
{
return
;
}
await
fs_extra_1
.
default
.
ensureDir
(
config
.
paths
.
artifacts
);
let
numberOfContracts
=
0
;
for
(
const
file
of
Object
.
values
(
compilationOutput
.
contracts
))
{
for
(
const
[
contractName
,
contractOutput
]
of
Object
.
entries
(
file
))
{
const
artifact
=
artifacts_1
.
getArtifactFromContractOutput
(
contractName
,
contractOutput
);
numberOfContracts
+=
1
;
artifact
.
storageLayout
=
contractOutput
.
storageLayout
;
await
artifacts_1
.
saveArtifact
(
config
.
paths
.
artifacts
,
artifact
);
}
}
console
.
log
(
'
Compiled
'
,
numberOfContracts
,
strings_1
.
pluralize
(
numberOfContracts
,
'
contract
'
),
'
successfully
'
);
});
//# sourceMappingURL=modify-compiler.js.map
\ No newline at end of file
packages/contracts/build/test/helpers/buidler/modify-compiler.js.map
0 → 100644
View file @
6e1dbfe0
{"version":3,"file":"modify-compiler.js","sourceRoot":"","sources":["../../../../test/helpers/buidler/modify-compiler.ts"],"names":[],"mappings":";;;;;AACA,wDAA8B;AAC9B,sDAAwD;AACxD,sEAAoE;AACpE,qEAG8C;AAC9C,4EAMoD;AAEpD,qBAAY,CACV,4CAA+B,EAC/B,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE;IACrC,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAA;IAG9B,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;IAE9D,OAAO,KAAK,CAAA;AACd,CAAC,CACF,CAAA;AAED,qBAAY,CAAC,iCAAoB,CAAC,CAAC,SAAS,CAC1C,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE;IACnC,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,0CAA6B,CAAC,CAAA;IAExD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;QACxB,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAA;QACjD,OAAM;KACP;IAED,MAAM,QAAQ,GAAY,MAAM,GAAG,CAAC,qCAAwB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;IAExE,IAAI,QAAQ,EAAE;QACZ,OAAO,CAAC,GAAG,CACT,iEAAiE,CAClE,CAAA;QACD,OAAM;KACP;IAED,MAAM,iBAAiB,GAAG,MAAM,GAAG,CAAC,iCAAoB,CAAC,CAAA;IAEzD,IAAI,iBAAiB,KAAK,SAAS,EAAE;QACnC,OAAM;KACP;IAED,MAAM,kBAAO,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IAC/C,IAAI,iBAAiB,GAAG,CAAC,CAAA;IAEzB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAM,iBAAiB,CAAC,SAAS,CAAC,EAAE;QAClE,KAAK,MAAM,CAAC,YAAY,EAAE,cAAc,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YACjE,MAAM,QAAQ,GAAQ,yCAA6B,CACjD,YAAY,EACZ,cAAc,CACf,CAAA;YACD,iBAAiB,IAAI,CAAC,CAAA;YAGtB,QAAQ,CAAC,aAAa,GAAI,cAAsB,CAAC,aAAa,CAAA;YAE9D,MAAM,wBAAY,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;SACrD;KACF;IAED,OAAO,CAAC,GAAG,CACT,UAAU,EACV,iBAAiB,EACjB,mBAAS,CAAC,iBAAiB,EAAE,UAAU,CAAC,EACxC,cAAc,CACf,CAAA;AACH,CAAC,CACF,CAAA"}
\ No newline at end of file
packages/contracts/build/test/helpers/constants.d.ts
0 → 100644
View file @
6e1dbfe0
export
declare
const
DEFAULT_ACCOUNTS
:
{
balance
:
string
;
secretKey
:
string
;
}[];
export
declare
const
DEFAULT_ACCOUNTS_BUIDLER
:
{
balance
:
string
;
privateKey
:
string
;
}[];
export
declare
const
OVM_TX_GAS_LIMIT
=
10000000
;
export
declare
const
RUN_OVM_TEST_GAS
=
20000000
;
export
declare
const
FORCE_INCLUSION_PERIOD_SECONDS
=
600
;
export
declare
const
NULL_BYTES32
:
string
;
export
declare
const
NON_NULL_BYTES32
:
string
;
export
declare
const
ZERO_ADDRESS
:
string
;
export
declare
const
NON_ZERO_ADDRESS
:
string
;
export
declare
const
VERIFIED_EMPTY_CONTRACT_HASH
=
"
0x00004B1DC0DE000000004B1DC0DE000000004B1DC0DE000000004B1DC0DE0000
"
;
export
declare
const
NUISANCE_GAS_COSTS
:
{
NUISANCE_GAS_SLOAD
:
number
;
NUISANCE_GAS_SSTORE
:
number
;
MIN_NUISANCE_GAS_PER_CONTRACT
:
number
;
NUISANCE_GAS_PER_CONTRACT_BYTE
:
number
;
MIN_GAS_FOR_INVALID_STATE_ACCESS
:
number
;
};
export
declare
const
Helper_TestRunner_BYTELEN
=
3654
;
export
declare
const
STORAGE_XOR
=
"
0xfeedfacecafebeeffeedfacecafebeeffeedfacecafebeeffeedfacecafebeef
"
;
export
declare
const
getStorageXOR
:
(
key
:
string
)
=>
string
;
packages/contracts/build/test/helpers/constants.js
0 → 100644
View file @
6e1dbfe0
"
use strict
"
;
var
__importDefault
=
(
this
&&
this
.
__importDefault
)
||
function
(
mod
)
{
return
(
mod
&&
mod
.
__esModule
)
?
mod
:
{
"
default
"
:
mod
};
};
Object
.
defineProperty
(
exports
,
"
__esModule
"
,
{
value
:
true
});
exports
.
getStorageXOR
=
exports
.
STORAGE_XOR
=
exports
.
Helper_TestRunner_BYTELEN
=
exports
.
NUISANCE_GAS_COSTS
=
exports
.
VERIFIED_EMPTY_CONTRACT_HASH
=
exports
.
NON_ZERO_ADDRESS
=
exports
.
ZERO_ADDRESS
=
exports
.
NON_NULL_BYTES32
=
exports
.
NULL_BYTES32
=
exports
.
FORCE_INCLUSION_PERIOD_SECONDS
=
exports
.
RUN_OVM_TEST_GAS
=
exports
.
OVM_TX_GAS_LIMIT
=
exports
.
DEFAULT_ACCOUNTS_BUIDLER
=
exports
.
DEFAULT_ACCOUNTS
=
void
0
;
const
ethers_1
=
require
(
"
ethers
"
);
const
ethereum_waffle_1
=
require
(
"
ethereum-waffle
"
);
const
buffer_xor_1
=
__importDefault
(
require
(
"
buffer-xor
"
));
const
utils_1
=
require
(
"
./utils
"
);
exports
.
DEFAULT_ACCOUNTS
=
ethereum_waffle_1
.
defaultAccounts
;
exports
.
DEFAULT_ACCOUNTS_BUIDLER
=
ethereum_waffle_1
.
defaultAccounts
.
map
((
account
)
=>
{
return
{
balance
:
ethers_1
.
ethers
.
BigNumber
.
from
(
account
.
balance
).
toHexString
(),
privateKey
:
account
.
secretKey
,
};
});
exports
.
OVM_TX_GAS_LIMIT
=
10000000
;
exports
.
RUN_OVM_TEST_GAS
=
20000000
;
exports
.
FORCE_INCLUSION_PERIOD_SECONDS
=
600
;
exports
.
NULL_BYTES32
=
utils_1
.
makeHexString
(
'
00
'
,
32
);
exports
.
NON_NULL_BYTES32
=
utils_1
.
makeHexString
(
'
11
'
,
32
);
exports
.
ZERO_ADDRESS
=
utils_1
.
makeAddress
(
'
00
'
);
exports
.
NON_ZERO_ADDRESS
=
utils_1
.
makeAddress
(
'
11
'
);
exports
.
VERIFIED_EMPTY_CONTRACT_HASH
=
'
0x00004B1DC0DE000000004B1DC0DE000000004B1DC0DE000000004B1DC0DE0000
'
;
exports
.
NUISANCE_GAS_COSTS
=
{
NUISANCE_GAS_SLOAD
:
20000
,
NUISANCE_GAS_SSTORE
:
20000
,
MIN_NUISANCE_GAS_PER_CONTRACT
:
30000
,
NUISANCE_GAS_PER_CONTRACT_BYTE
:
100
,
MIN_GAS_FOR_INVALID_STATE_ACCESS
:
30000
,
};
exports
.
Helper_TestRunner_BYTELEN
=
3654
;
exports
.
STORAGE_XOR
=
'
0xfeedfacecafebeeffeedfacecafebeeffeedfacecafebeeffeedfacecafebeef
'
;
exports
.
getStorageXOR
=
(
key
)
=>
{
return
utils_1
.
toHexString
(
buffer_xor_1
.
default
(
utils_1
.
fromHexString
(
key
),
utils_1
.
fromHexString
(
exports
.
STORAGE_XOR
)));
};
//# sourceMappingURL=constants.js.map
\ No newline at end of file
packages/contracts/build/test/helpers/constants.js.map
0 → 100644
View file @
6e1dbfe0
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../test/helpers/constants.ts"],"names":[],"mappings":";;;;;;AACA,mCAA+B;AAC/B,qDAAiD;AACjD,4DAA4B;AAG5B,mCAAgF;AAEnE,QAAA,gBAAgB,GAAG,iCAAe,CAAA;AAClC,QAAA,wBAAwB,GAAG,iCAAe,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;IACtE,OAAO;QACL,OAAO,EAAE,eAAM,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE;QAC7D,UAAU,EAAE,OAAO,CAAC,SAAS;KAC9B,CAAA;AACH,CAAC,CAAC,CAAA;AAEW,QAAA,gBAAgB,GAAG,QAAU,CAAA;AAC7B,QAAA,gBAAgB,GAAG,QAAU,CAAA;AAC7B,QAAA,8BAA8B,GAAG,GAAG,CAAA;AAEpC,QAAA,YAAY,GAAG,qBAAa,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;AACtC,QAAA,gBAAgB,GAAG,qBAAa,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;AAC1C,QAAA,YAAY,GAAG,mBAAW,CAAC,IAAI,CAAC,CAAA;AAChC,QAAA,gBAAgB,GAAG,mBAAW,CAAC,IAAI,CAAC,CAAA;AAEpC,QAAA,4BAA4B,GACvC,oEAAoE,CAAA;AAEzD,QAAA,kBAAkB,GAAG;IAChC,kBAAkB,EAAE,KAAK;IACzB,mBAAmB,EAAE,KAAK;IAC1B,6BAA6B,EAAE,KAAK;IACpC,8BAA8B,EAAE,GAAG;IACnC,gCAAgC,EAAE,KAAK;CACxC,CAAA;AAGY,QAAA,yBAAyB,GAAG,IAAI,CAAA;AAEhC,QAAA,WAAW,GAAG,oEAAoE,CAAA;AAClF,QAAA,aAAa,GAAG,CAAC,GAAW,EAAU,EAAE;IACnD,OAAO,mBAAW,CAAC,oBAAG,CAAC,qBAAa,CAAC,GAAG,CAAC,EAAE,qBAAa,CAAC,mBAAW,CAAC,CAAC,CAAC,CAAA;AACzE,CAAC,CAAA"}
\ No newline at end of file
packages/contracts/build/test/helpers/utils/buffer-utils.d.ts
0 → 100644
View file @
6e1dbfe0
/// <reference types="node" />
export
declare
const
toHexString
:
(
buf
:
Buffer
|
string
)
=>
string
;
export
declare
const
fromHexString
:
(
str
:
string
|
Buffer
)
=>
Buffer
;
packages/contracts/build/test/helpers/utils/buffer-utils.js
0 → 100644
View file @
6e1dbfe0
"
use strict
"
;
Object
.
defineProperty
(
exports
,
"
__esModule
"
,
{
value
:
true
});
exports
.
fromHexString
=
exports
.
toHexString
=
void
0
;
exports
.
toHexString
=
(
buf
)
=>
{
return
'
0x
'
+
exports
.
fromHexString
(
buf
).
toString
(
'
hex
'
);
};
exports
.
fromHexString
=
(
str
)
=>
{
if
(
typeof
str
===
'
string
'
&&
str
.
startsWith
(
'
0x
'
))
{
return
Buffer
.
from
(
str
.
slice
(
2
),
'
hex
'
);
}
return
Buffer
.
from
(
str
);
};
//# sourceMappingURL=buffer-utils.js.map
\ No newline at end of file
packages/contracts/build/test/helpers/utils/buffer-utils.js.map
0 → 100644
View file @
6e1dbfe0
{"version":3,"file":"buffer-utils.js","sourceRoot":"","sources":["../../../../test/helpers/utils/buffer-utils.ts"],"names":[],"mappings":";;;AAKa,QAAA,WAAW,GAAG,CAAC,GAAoB,EAAU,EAAE;IAC1D,OAAO,IAAI,GAAG,qBAAa,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AAClD,CAAC,CAAA;AAOY,QAAA,aAAa,GAAG,CAAC,GAAoB,EAAU,EAAE;IAC5D,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE;QACnD,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;KACxC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACzB,CAAC,CAAA"}
\ No newline at end of file
packages/contracts/build/test/helpers/utils/byte-utils.d.ts
0 → 100644
View file @
6e1dbfe0
export
declare
const
makeHexString
:
(
byte
:
string
,
len
:
number
)
=>
string
;
export
declare
const
makeAddress
:
(
byte
:
string
)
=>
string
;
export
declare
const
remove0x
:
(
str
:
string
)
=>
string
;
packages/contracts/build/test/helpers/utils/byte-utils.js
0 → 100644
View file @
6e1dbfe0
"
use strict
"
;
Object
.
defineProperty
(
exports
,
"
__esModule
"
,
{
value
:
true
});
exports
.
remove0x
=
exports
.
makeAddress
=
exports
.
makeHexString
=
void
0
;
exports
.
makeHexString
=
(
byte
,
len
)
=>
{
return
'
0x
'
+
byte
.
repeat
(
len
);
};
exports
.
makeAddress
=
(
byte
)
=>
{
return
exports
.
makeHexString
(
byte
,
20
);
};
exports
.
remove0x
=
(
str
)
=>
{
if
(
str
.
startsWith
(
'
0x
'
))
{
return
str
.
slice
(
2
);
}
else
{
return
str
;
}
};
//# sourceMappingURL=byte-utils.js.map
\ No newline at end of file
packages/contracts/build/test/helpers/utils/byte-utils.js.map
0 → 100644
View file @
6e1dbfe0
{"version":3,"file":"byte-utils.js","sourceRoot":"","sources":["../../../../test/helpers/utils/byte-utils.ts"],"names":[],"mappings":";;;AAMa,QAAA,aAAa,GAAG,CAAC,IAAY,EAAE,GAAW,EAAU,EAAE;IACjE,OAAO,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;AAChC,CAAC,CAAA;AAOY,QAAA,WAAW,GAAG,CAAC,IAAY,EAAU,EAAE;IAClD,OAAO,qBAAa,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;AAChC,CAAC,CAAA;AAOY,QAAA,QAAQ,GAAG,CAAC,GAAW,EAAU,EAAE;IAC9C,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE;QACxB,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;KACpB;SAAM;QACL,OAAO,GAAG,CAAA;KACX;AACH,CAAC,CAAA"}
\ No newline at end of file
packages/contracts/build/test/helpers/utils/index.d.ts
0 → 100644
View file @
6e1dbfe0
export
*
from
'
./buffer-utils
'
;
export
*
from
'
./byte-utils
'
;
packages/contracts/build/test/helpers/utils/index.js
0 → 100644
View file @
6e1dbfe0
"
use strict
"
;
var
__createBinding
=
(
this
&&
this
.
__createBinding
)
||
(
Object
.
create
?
(
function
(
o
,
m
,
k
,
k2
)
{
if
(
k2
===
undefined
)
k2
=
k
;
Object
.
defineProperty
(
o
,
k2
,
{
enumerable
:
true
,
get
:
function
()
{
return
m
[
k
];
}
});
})
:
(
function
(
o
,
m
,
k
,
k2
)
{
if
(
k2
===
undefined
)
k2
=
k
;
o
[
k2
]
=
m
[
k
];
}));
var
__exportStar
=
(
this
&&
this
.
__exportStar
)
||
function
(
m
,
exports
)
{
for
(
var
p
in
m
)
if
(
p
!==
"
default
"
&&
!
Object
.
prototype
.
hasOwnProperty
.
call
(
exports
,
p
))
__createBinding
(
exports
,
m
,
p
);
};
Object
.
defineProperty
(
exports
,
"
__esModule
"
,
{
value
:
true
});
__exportStar
(
require
(
"
./buffer-utils
"
),
exports
);
__exportStar
(
require
(
"
./byte-utils
"
),
exports
);
//# sourceMappingURL=index.js.map
\ No newline at end of file
packages/contracts/build/test/helpers/utils/index.js.map
0 → 100644
View file @
6e1dbfe0
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../test/helpers/utils/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,iDAA8B;AAC9B,+CAA4B"}
\ No newline at end of file
packages/contracts/contracts/optimistic-ethereum/OVM/bridge/OVM_L1CrossDomainMessenger.sol
View file @
6e1dbfe0
...
...
@@ -2,10 +2,8 @@
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Proxy Imports */
import { Proxy_Resolver } from "../../proxy/Proxy_Resolver.sol";
/* Library Imports */
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
import { Lib_EthMerkleTrie } from "../../libraries/trie/Lib_EthMerkleTrie.sol";
import { Lib_ByteUtils } from "../../libraries/utils/Lib_ByteUtils.sol";
...
...
@@ -20,7 +18,7 @@ import { OVM_BaseCrossDomainMessenger } from "./OVM_BaseCrossDomainMessenger.sol
/**
* @title OVM_L1CrossDomainMessenger
*/
contract OVM_L1CrossDomainMessenger is iOVM_L1CrossDomainMessenger, OVM_BaseCrossDomainMessenger,
Proxy_
Resolver {
contract OVM_L1CrossDomainMessenger is iOVM_L1CrossDomainMessenger, OVM_BaseCrossDomainMessenger,
Lib_Address
Resolver {
/*******************************************
* Contract Variables: Contract References *
...
...
@@ -35,12 +33,12 @@ contract OVM_L1CrossDomainMessenger is iOVM_L1CrossDomainMessenger, OVM_BaseCros
***************/
/**
* @param _
proxyManager Address of the Proxy_
Manager.
* @param _
libAddressManager Address of the Address
Manager.
*/
constructor(
address _
proxy
Manager
address _
libAddress
Manager
)
Proxy_Resolver(_proxy
Manager)
Lib_AddressResolver(_libAddress
Manager)
{
ovmL1ToL2TransactionQueue = iOVM_L1ToL2TransactionQueue(resolve("OVM_L1ToL2TransactionQueue"));
ovmStateCommitmentChain = iOVM_StateCommitmentChain(resolve("OVM_StateCommitmentChain"));
...
...
packages/contracts/contracts/optimistic-ethereum/OVM/bridge/OVM_L2CrossDomainMessenger.sol
View file @
6e1dbfe0
...
...
@@ -2,8 +2,8 @@
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/*
Prox
y Imports */
import {
Proxy_Resolver } from "../../proxy/Proxy_
Resolver.sol";
/*
Librar
y Imports */
import {
Lib_AddressResolver } from "../../libraries/resolver/Lib_Address
Resolver.sol";
/* Interface Imports */
import { iOVM_L2CrossDomainMessenger } from "../../iOVM/bridge/iOVM_L2CrossDomainMessenger.sol";
...
...
@@ -16,7 +16,7 @@ import { OVM_BaseCrossDomainMessenger } from "./OVM_BaseCrossDomainMessenger.sol
/**
* @title OVM_L2CrossDomainMessenger
*/
contract OVM_L2CrossDomainMessenger is iOVM_L2CrossDomainMessenger, OVM_BaseCrossDomainMessenger,
Proxy_
Resolver {
contract OVM_L2CrossDomainMessenger is iOVM_L2CrossDomainMessenger, OVM_BaseCrossDomainMessenger,
Lib_Address
Resolver {
/*******************************************
* Contract Variables: Contract References *
...
...
@@ -31,12 +31,12 @@ contract OVM_L2CrossDomainMessenger is iOVM_L2CrossDomainMessenger, OVM_BaseCros
***************/
/**
* @param _
proxyManager Address of the Proxy_
Manager.
* @param _
libAddressManager Address of the Address
Manager.
*/
constructor(
address _
proxy
Manager
address _
libAddress
Manager
)
Proxy_Resolver(_proxy
Manager)
Lib_AddressResolver(_libAddress
Manager)
{
ovmL1MessageSender = iOVM_L1MessageSender(resolve("OVM_L1MessageSender"));
ovmL2ToL1MessagePasser = iOVM_L2ToL1MessagePasser(resolve("OVM_L2ToL1MessagePasser"));
...
...
packages/contracts/contracts/optimistic-ethereum/OVM/chain/OVM_CanonicalTransactionChain.sol
View file @
6e1dbfe0
...
...
@@ -2,11 +2,9 @@
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Proxy Imports */
import { Proxy_Resolver } from "../../proxy/Proxy_Resolver.sol";
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
import { Lib_MerkleUtils } from "../../libraries/utils/Lib_MerkleUtils.sol";
/* Interface Imports */
...
...
@@ -19,7 +17,7 @@ import { OVM_BaseChain } from "./OVM_BaseChain.sol";
/**
* @title OVM_CanonicalTransactionChain
*/
contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, OVM_BaseChain,
Proxy_
Resolver {
contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, OVM_BaseChain,
Lib_Address
Resolver {
/*******************************************
* Contract Variables: Contract References *
...
...
@@ -41,14 +39,14 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, OVM_Ba
***************/
/**
* @param _
proxyManager Address of the Proxy_
Manager.
* @param _
libAddressManager Address of the Address
Manager.
* @param _forceInclusionPeriodSeconds Period during which only the sequencer can submit.
*/
constructor(
address _
proxy
Manager,
address _
libAddress
Manager,
uint256 _forceInclusionPeriodSeconds
)
Proxy_Resolver(_proxy
Manager)
Lib_AddressResolver(_libAddress
Manager)
{
ovmL1ToL2TransactionQueue = iOVM_L1ToL2TransactionQueue(resolve("OVM_L1ToL2TransactionQueue"));
forceInclusionPeriodSeconds = _forceInclusionPeriodSeconds;
...
...
packages/contracts/contracts/optimistic-ethereum/OVM/chain/OVM_StateCommitmentChain.sol
View file @
6e1dbfe0
...
...
@@ -2,11 +2,9 @@
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Proxy Imports */
import { Proxy_Resolver } from "../../proxy/Proxy_Resolver.sol";
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
/* Interface Imports */
import { iOVM_FraudVerifier } from "../../iOVM/verification/iOVM_FraudVerifier.sol";
...
...
@@ -19,7 +17,7 @@ import { OVM_BaseChain } from "./OVM_BaseChain.sol";
/**
* @title OVM_StateCommitmentChain
*/
contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, OVM_BaseChain,
Proxy_
Resolver {
contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, OVM_BaseChain,
Lib_Address
Resolver {
/*******************************************
* Contract Variables: Contract References *
...
...
@@ -34,12 +32,12 @@ contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, OVM_BaseChain, P
***************/
/**
* @param _
proxyManager Address of the Proxy_
Manager.
* @param _
libAddressManager Address of the Address
Manager.
*/
constructor(
address _
proxy
Manager
address _
libAddress
Manager
)
Proxy_Resolver(_proxy
Manager)
Lib_AddressResolver(_libAddress
Manager)
{
ovmCanonicalTransactionChain = iOVM_CanonicalTransactionChain(resolve("OVM_CanonicalTransactionChain"));
ovmFraudVerifier = iOVM_FraudVerifier(resolve("OVM_FraudVerifier"));
...
...
packages/contracts/contracts/optimistic-ethereum/OVM/queue/OVM_L1ToL2TransactionQueue.sol
View file @
6e1dbfe0
...
...
@@ -2,11 +2,9 @@
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Proxy Imports */
import { Proxy_Resolver } from "../../proxy/Proxy_Resolver.sol";
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
/* Interface Imports */
import { iOVM_L1ToL2TransactionQueue } from "../../iOVM/queue/iOVM_L1ToL2TransactionQueue.sol";
...
...
@@ -17,7 +15,7 @@ import { OVM_BaseQueue } from "./OVM_BaseQueue.sol";
/**
* @title OVM_L1ToL2TransactionQueue
*/
contract OVM_L1ToL2TransactionQueue is iOVM_L1ToL2TransactionQueue, OVM_BaseQueue,
Proxy_
Resolver {
contract OVM_L1ToL2TransactionQueue is iOVM_L1ToL2TransactionQueue, OVM_BaseQueue,
Lib_Address
Resolver {
/*******************************************
* Contract Variables: Contract References *
...
...
@@ -31,12 +29,12 @@ contract OVM_L1ToL2TransactionQueue is iOVM_L1ToL2TransactionQueue, OVM_BaseQueu
***************/
/**
* @param _
proxyManager Address of the Proxy_
Manager.
* @param _
libAddressManager Address of the Address
Manager.
*/
constructor(
address _
proxy
Manager
address _
libAddress
Manager
)
Proxy_Resolver(_proxy
Manager)
Lib_AddressResolver(_libAddress
Manager)
{
ovmCanonicalTransactionChain = resolve("OVM_CanonicalTransactionChain");
}
...
...
packages/contracts/contracts/optimistic-ethereum/OVM/verification/OVM_FraudVerifier.sol
View file @
6e1dbfe0
...
...
@@ -2,11 +2,9 @@
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Proxy Imports */
import { Proxy_Resolver } from "../../proxy/Proxy_Resolver.sol";
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
/* Interface Imports */
import { iOVM_FraudVerifier } from "../../iOVM/verification/iOVM_FraudVerifier.sol";
...
...
@@ -17,7 +15,7 @@ import { iOVM_StateManagerFactory } from "../../iOVM/execution/iOVM_StateManager
import { iOVM_StateCommitmentChain } from "../../iOVM/chain/iOVM_StateCommitmentChain.sol";
import { iOVM_CanonicalTransactionChain } from "../../iOVM/chain/iOVM_CanonicalTransactionChain.sol";
contract OVM_FraudVerifier is iOVM_FraudVerifier,
Proxy_
Resolver {
contract OVM_FraudVerifier is iOVM_FraudVerifier,
Lib_Address
Resolver {
/*******************************************
* Contract Variables: Contract References *
...
...
@@ -39,12 +37,12 @@ contract OVM_FraudVerifier is iOVM_FraudVerifier, Proxy_Resolver {
***************/
/**
* @param _
proxyManager Address of the Proxy_
Manager.
* @param _
libAddressManager Address of the Address
Manager.
*/
constructor(
address _
proxy
Manager
address _
libAddress
Manager
)
Proxy_Resolver(_proxy
Manager)
Lib_AddressResolver(_libAddress
Manager)
{
ovmStateCommitmentChain = iOVM_StateCommitmentChain(resolve("OVM_StateCommitmentChain"));
ovmCanonicalTransactionChain = iOVM_CanonicalTransactionChain(resolve("OVM_CanonicalTransactionChain"));
...
...
@@ -123,7 +121,7 @@ contract OVM_FraudVerifier is iOVM_FraudVerifier, Proxy_Resolver {
transitioners[_preStateRoot] = iOVM_StateTransitionerFactory(
resolve("OVM_StateTransitionerFactory")
).create(
address(
proxy
Manager),
address(
libAddress
Manager),
_preStateRootProof.index,
_preStateRoot,
Lib_OVMCodec.hashTransaction(_transaction)
...
...
packages/contracts/contracts/optimistic-ethereum/OVM/verification/OVM_StateTransitioner.sol
View file @
6e1dbfe0
...
...
@@ -2,11 +2,9 @@
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Proxy Imports */
import { Proxy_Resolver } from "../../proxy/Proxy_Resolver.sol";
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
import { Lib_EthUtils } from "../../libraries/utils/Lib_EthUtils.sol";
import { Lib_EthMerkleTrie } from "../../libraries/trie/Lib_EthMerkleTrie.sol";
...
...
@@ -19,7 +17,7 @@ import { iOVM_StateManagerFactory } from "../../iOVM/execution/iOVM_StateManager
/**
* @title OVM_StateTransitioner
*/
contract OVM_StateTransitioner is iOVM_StateTransitioner,
Proxy_
Resolver {
contract OVM_StateTransitioner is iOVM_StateTransitioner,
Lib_Address
Resolver {
/*******************
* Data Structures *
...
...
@@ -56,18 +54,18 @@ contract OVM_StateTransitioner is iOVM_StateTransitioner, Proxy_Resolver {
***************/
/**
* @param _
proxyManager Address of the Proxy_
Manager.
* @param _
libAddressManager Address of the Address
Manager.
* @param _stateTransitionIndex Index of the state transition being verified.
* @param _preStateRoot State root before the transition was executed.
* @param _transactionHash Hash of the executed transaction.
*/
constructor(
address _
proxy
Manager,
address _
libAddress
Manager,
uint256 _stateTransitionIndex,
bytes32 _preStateRoot,
bytes32 _transactionHash
)
Proxy_Resolver(_proxy
Manager)
Lib_AddressResolver(_libAddress
Manager)
{
stateTransitionIndex = _stateTransitionIndex;
preStateRoot = _preStateRoot;
...
...
@@ -253,7 +251,7 @@ contract OVM_StateTransitioner is iOVM_StateTransitioner, Proxy_Resolver {
// TODO: Set state manager for EM here.
ovmStateManager.setExecutionManager(resolve
Target
("OVM_ExecutionManager"));
ovmStateManager.setExecutionManager(resolve("OVM_ExecutionManager"));
ovmExecutionManager.run(_transaction, address(ovmStateManager));
phase = TransitionPhase.POST_EXECUTION;
...
...
packages/contracts/contracts/optimistic-ethereum/OVM/verification/OVM_StateTransitionerFactory.sol
View file @
6e1dbfe0
...
...
@@ -19,14 +19,14 @@ contract OVM_StateTransitionerFactory is iOVM_StateTransitionerFactory {
/**
* Creates a new OVM_StateTransitioner
* @param _
proxyManager Address of the Proxy_
Manager.
* @param _
libAddressManager Address of the Address
Manager.
* @param _stateTransitionIndex Index of the state transition being verified.
* @param _preStateRoot State root before the transition was executed.
* @param _transactionHash Hash of the executed transaction.
* @return _ovmStateTransitioner New OVM_StateTransitioner instance.
*/
function create(
address _
proxy
Manager,
address _
libAddress
Manager,
uint256 _stateTransitionIndex,
bytes32 _preStateRoot,
bytes32 _transactionHash
...
...
@@ -38,7 +38,7 @@ contract OVM_StateTransitionerFactory is iOVM_StateTransitionerFactory {
)
{
return new OVM_StateTransitioner(
_
proxy
Manager,
_
libAddress
Manager,
_stateTransitionIndex,
_preStateRoot,
_transactionHash
...
...
packages/contracts/contracts/optimistic-ethereum/libraries/resolver/Lib_AddressManager.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/**
* @title Lib_AddressManager
*/
contract Lib_AddressManager {
/*******************************************
* Contract Variables: Internal Accounting *
*******************************************/
mapping (bytes32 => address) private addresses;
/********************
* Public Functions *
********************/
function setAddress(
string memory _name,
address _address
)
public
{
addresses[_getNameHash(_name)] = _address;
}
function getAddress(
string memory _name
)
public
view
returns (address)
{
return addresses[_getNameHash(_name)];
}
/**********************
* Internal Functions *
**********************/
function _getNameHash(
string memory _name
)
internal
pure
returns (
bytes32 _hash
)
{
return keccak256(abi.encodePacked(_name));
}
}
packages/contracts/contracts/optimistic-ethereum/libraries/resolver/Lib_AddressResolver.sol
0 → 100644
View file @
6e1dbfe0
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/* Library Imports */
import { Lib_AddressManager } from "./Lib_AddressManager.sol";
/**
* @title Lib_AddressResolver
*/
contract Lib_AddressResolver {
/*******************************************
* Contract Variables: Contract References *
*******************************************/
Lib_AddressManager internal libAddressManager;
/***************
* Constructor *
***************/
/**
* @param _libAddressManager Address of the Lib_AddressManager.
*/
constructor(
address _libAddressManager
)
public
{
libAddressManager = Lib_AddressManager(_libAddressManager);
}
/********************
* Public Functions *
********************/
function resolve(
string memory _name
)
public
view
returns (
address _contract
)
{
return libAddressManager.getAddress(_name);
}
}
packages/contracts/package.json
View file @
6e1dbfe0
...
...
@@ -4,12 +4,15 @@
"main"
:
"index.js"
,
"license"
:
"MIT"
,
"scripts"
:
{
"build"
:
"yarn run build:contracts"
,
"build"
:
"yarn run build:contracts && yarn run build:typescript && yarn run build:copy"
,
"build:typescript"
:
"tsc -p ."
,
"build:contracts"
:
"buidler compile"
,
"build:copy"
:
"copyfiles -u 2
\"
contracts/optimistic-ethereum/**/*.sol
\"
\"
build/contracts
\"
"
,
"test"
:
"yarn run test:contracts"
,
"test:contracts"
:
"buidler test"
,
"lint"
:
"tslint --format stylish --project ."
,
"fix"
:
"prettier --config prettier-config.json --write
\"
buidler.config.ts
\"
\"
{src,test}/**/*.ts
\"
"
"fix"
:
"prettier --config prettier-config.json --write
\"
buidler.config.ts
\"
\"
{src,test}/**/*.ts
\"
"
,
"clean"
:
"rm -rf ./artifacts ./build ./cache"
},
"devDependencies"
:
{
"@nomiclabs/buidler"
:
"^1.4.4"
,
...
...
@@ -22,6 +25,7 @@
"assert"
:
"^2.0.0"
,
"buffer-xor"
:
"^2.0.2"
,
"chai"
:
"^4.2.0"
,
"copyfiles"
:
"^2.3.0"
,
"ethereum-waffle"
:
"3.0.0"
,
"ethers"
:
"5.0.0"
,
"fs-extra"
:
"^9.0.1"
,
...
...
packages/contracts/test/helpers/constants.ts
View file @
6e1dbfe0
...
...
@@ -16,6 +16,7 @@ export const DEFAULT_ACCOUNTS_BUIDLER = defaultAccounts.map((account) => {
export
const
OVM_TX_GAS_LIMIT
=
10
_000_000
export
const
RUN_OVM_TEST_GAS
=
20
_000_000
export
const
FORCE_INCLUSION_PERIOD_SECONDS
=
600
export
const
NULL_BYTES32
=
makeHexString
(
'
00
'
,
32
)
export
const
NON_NULL_BYTES32
=
makeHexString
(
'
11
'
,
32
)
...
...
packages/contracts/tsconfig.json
View file @
6e1dbfe0
...
...
@@ -21,7 +21,7 @@
]
},
"include"
:
[
"*.ts"
,
"**/*.ts"
,
"artifacts/*.json"
],
"exclude"
:
[
"./build"
,
"node_modules"
],
"exclude"
:
[
"./build"
,
"node_modules"
,
"test"
],
"files"
:
[
"./buidler.config.ts"
,
"./buidler-env.d.ts"
,
...
...
packages/contracts/yarn.lock
View file @
6e1dbfe0
...
...
@@ -887,6 +887,11 @@ ansi-regex@^4.1.0:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
ansi-regex@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
...
...
@@ -899,7 +904,7 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1:
dependencies:
color-convert "^1.9.0"
ansi-styles@^4.1.0:
ansi-styles@^4.
0.0, ansi-styles@^4.
1.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359"
integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==
...
...
@@ -2284,6 +2289,15 @@ cliui@^5.0.0:
strip-ansi "^5.2.0"
wrap-ansi "^5.1.0"
cliui@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==
dependencies:
string-width "^4.2.0"
strip-ansi "^6.0.0"
wrap-ansi "^6.2.0"
clone-buffer@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58"
...
...
@@ -2468,6 +2482,18 @@ copy-props@^2.0.1:
each-props "^1.3.0"
is-plain-object "^2.0.1"
copyfiles@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/copyfiles/-/copyfiles-2.3.0.tgz#1c26ebbe3d46bba2d309a3fd8e3aaccf53af8c76"
integrity sha512-73v7KFuDFJ/ofkQjZBMjMBFWGgkS76DzXvBMUh7djsMOE5EELWtAO/hRB6Wr5Vj5Zg+YozvoHemv0vnXpqxmOQ==
dependencies:
glob "^7.0.5"
minimatch "^3.0.3"
mkdirp "^1.0.4"
noms "0.0.0"
through2 "^2.0.1"
yargs "^15.3.1"
core-js-pure@^3.0.1:
version "3.6.5"
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813"
...
...
@@ -2916,6 +2942,11 @@ emoji-regex@^7.0.1:
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
emoji-regex@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
encodeurl@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
...
...
@@ -3934,6 +3965,14 @@ find-up@^2.1.0:
dependencies:
locate-path "^2.0.0"
find-up@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
dependencies:
locate-path "^5.0.0"
path-exists "^4.0.0"
find-yarn-workspace-root@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db"
...
...
@@ -4319,7 +4358,7 @@ glob@7.1.3:
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@7.1.6, glob@^7.1.1, glob@^7.1.3, glob@~7.1.6:
glob@7.1.6, glob@^7.
0.5, glob@^7.
1.1, glob@^7.1.3, glob@~7.1.6:
version "7.1.6"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
...
...
@@ -4941,6 +4980,11 @@ is-fullwidth-code-point@^2.0.0:
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
is-fullwidth-code-point@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
is-function@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08"
...
...
@@ -5639,6 +5683,13 @@ locate-path@^3.0.0:
p-locate "^3.0.0"
path-exists "^3.0.0"
locate-path@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
dependencies:
p-locate "^4.1.0"
locate-path@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
...
...
@@ -5923,7 +5974,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
minimatch@3.0.4, minimatch@^3.0.4:
minimatch@3.0.4, minimatch@^3.0.
3, minimatch@^3.0.
4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
...
...
@@ -5965,7 +6016,7 @@ mkdirp-promise@^5.0.1:
dependencies:
mkdirp "*"
mkdirp@*:
mkdirp@*
, mkdirp@^1.0.4
:
version "1.0.4"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
...
...
@@ -6141,6 +6192,14 @@ node-gyp-build@^4.2.0:
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.2.3.tgz#ce6277f853835f718829efb47db20f3e4d9c4739"
integrity sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==
noms@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/noms/-/noms-0.0.0.tgz#da8ebd9f3af9d6760919b27d9cdc8092a7332859"
integrity sha1-2o69nzr51nYJGbJ9nNyAkqczKFk=
dependencies:
inherits "^2.0.1"
readable-stream "~1.0.31"
normalize-package-data@^2.3.2:
version "2.5.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
...
...
@@ -6404,7 +6463,7 @@ p-limit@^1.1.0:
dependencies:
p-try "^1.0.0"
p-limit@^2.0.0:
p-limit@^2.0.0
, p-limit@^2.2.0
:
version "2.3.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
...
...
@@ -6432,6 +6491,13 @@ p-locate@^3.0.0:
dependencies:
p-limit "^2.0.0"
p-locate@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
dependencies:
p-limit "^2.2.0"
p-locate@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
...
...
@@ -6974,7 +7040,7 @@ readable-stream@^3.0.6, readable-stream@^3.6.0:
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
readable-stream@~1.0.15:
readable-stream@~1.0.15
, readable-stream@~1.0.31
:
version "1.0.34"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=
...
...
@@ -7771,6 +7837,15 @@ string-width@^3.0.0, string-width@^3.1.0:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^5.1.0"
string-width@^4.1.0, string-width@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5"
integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.0"
string.prototype.trim@~1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.1.tgz#141233dff32c82bfad80684d7e5f0869ee0fb782"
...
...
@@ -7836,6 +7911,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
dependencies:
ansi-regex "^4.1.0"
strip-ansi@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==
dependencies:
ansi-regex "^5.0.0"
strip-bom@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
...
...
@@ -7993,7 +8075,7 @@ through2-filter@^3.0.0:
through2 "~2.0.0"
xtend "~4.0.0"
through2@^2.0.0, through2@^2.0.3, through2@~2.0.0:
through2@^2.0.0, through2@^2.0.
1, through2@^2.0.
3, through2@~2.0.0:
version "2.0.5"
resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
...
...
@@ -8915,6 +8997,15 @@ wrap-ansi@^5.1.0:
string-width "^3.0.0"
strip-ansi "^5.0.0"
wrap-ansi@^6.2.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
...
...
@@ -9044,6 +9135,14 @@ yargs-parser@^15.0.1:
camelcase "^5.0.0"
decamelize "^1.2.0"
yargs-parser@^18.1.2:
version "18.1.3"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==
dependencies:
camelcase "^5.0.0"
decamelize "^1.2.0"
yargs-parser@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4"
...
...
@@ -9105,6 +9204,23 @@ yargs@^14.2.3:
y18n "^4.0.0"
yargs-parser "^15.0.1"
yargs@^15.3.1:
version "15.4.1"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==
dependencies:
cliui "^6.0.0"
decamelize "^1.2.0"
find-up "^4.1.0"
get-caller-file "^2.0.1"
require-directory "^2.1.1"
require-main-filename "^2.0.0"
set-blocking "^2.0.0"
string-width "^4.2.0"
which-module "^2.0.0"
y18n "^4.0.0"
yargs-parser "^18.1.2"
yargs@^4.7.1:
version "4.8.1"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment