Skip to content

Commit

Permalink
docking to l2output oracle and dgf contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
guoshijiang committed Dec 19, 2024
1 parent d69aa0b commit c0cc7d1
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/bls/BLSApkRegistry.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
pragma solidity ^0.8.20;

import "../interfaces/IBLSApkRegistry.sol";

Expand Down
2 changes: 1 addition & 1 deletion src/bls/BLSApkRegistryStorage.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
pragma solidity ^0.8.20;

import {IBLSApkRegistry} from "../interfaces/IBLSApkRegistry.sol";
import {Initializable} from "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol";
Expand Down
36 changes: 31 additions & 5 deletions src/core/FinalityRelayerManager.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
pragma solidity ^0.8.20;

import {OwnableUpgradeable} from "@openzeppelin-upgrades/contracts/access/OwnableUpgradeable.sol";

import "../libraries/SafeCall.sol";

import "../interfaces/IFinalityRelayerManager.sol";
import "../interfaces/IBLSApkRegistry.sol";
import "./FinalityRelayerManagerStorage.sol";
Expand All @@ -18,14 +20,18 @@ contract FinalityRelayerManager is OwnableUpgradeable, FinalityRelayerManagerSto
}

constructor(
address _blsApkRegistry
) FinalityRelayerManagerStorage(IBLSApkRegistry(_blsApkRegistry)) {
address _blsApkRegistry,
address _l2OutputOracle,
address _disputeGameFactory
) FinalityRelayerManagerStorage(IBLSApkRegistry(_blsApkRegistry), _l2OutputOracle, _disputeGameFactory) {
_disableInitializers();
}

function initialize(
address initialOwner
address initialOwner,
bool _isDisputeGameFactory
) external initializer {
isDisputeGameFactory = _isDisputeGameFactory;
_transferOwnership(initialOwner);
}

Expand All @@ -49,12 +55,32 @@ contract FinalityRelayerManager is OwnableUpgradeable, FinalityRelayerManagerSto

function VerifyFinalitySignature(
FinalityBatch calldata finalityBatch,
IBLSApkRegistry.FinalityNonSingerAndSignature memory finalityNonSingerAndSignature
IBLSApkRegistry.FinalityNonSingerAndSignature memory finalityNonSingerAndSignature,
uint256 minGas
) external {
(
IBLSApkRegistry.StakeTotals memory stakeTotals,
bytes32 signatoryRecordHash
) = blsApkRegistry.checkSignatures(finalityBatch.msgHash, finalityBatch.l2BlockNumber, finalityNonSingerAndSignature);

// call l2output oracle contacts
if (!isDisputeGameFactory) {
bool success = SafeCall.callWithMinGas(
l2OutputOracle,
minGas,
0,
abi.encodeWithSignature("proposeL2Output(bytes32,uint256,bytes32,uint256)", finalityBatch.stateRoot, finalityBatch.l2BlockNumber, finalityBatch.l1BlockHash, finalityBatch.l1BlockNumber)
);
require(success, "StrategyBase.VerifyFinalitySignature: proposeL2Output stateroot failed");
} else {
bool success = SafeCall.callWithMinGas(
disputeGameFactory,
minGas,
0,
abi.encodeWithSignature("create(uint32,bytes32,bytes)", finalityBatch.disputeGameType, finalityBatch.stateRoot, '0x')
);
require(success, "StrategyBase.VerifyFinalitySignature: create game failed");
}
emit VerifyFinalitySig(stakeTotals.totalBtcStaking, stakeTotals.totalMantaStaking, signatoryRecordHash);
}

Expand Down
12 changes: 10 additions & 2 deletions src/core/FinalityRelayerManagerStorage.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
pragma solidity ^0.8.20;

import {Initializable} from "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol";

Expand All @@ -12,8 +12,16 @@ abstract contract FinalityRelayerManagerStorage is Initializable {

IBLSApkRegistry public blsApkRegistry;

constructor(IBLSApkRegistry _blsApkRegistry) {
address public l2OutputOracle;

address public disputeGameFactory;

bool public isDisputeGameFactory;

constructor(IBLSApkRegistry _blsApkRegistry, address _l2OutputOracle, address _disputeGameFactory) {
blsApkRegistry = _blsApkRegistry;
l2OutputOracle = _l2OutputOracle;
disputeGameFactory = _disputeGameFactory;
_disableInitializers();
}

Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/IBLSApkRegistry.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
pragma solidity ^0.8.20;

import {BN254} from "../libraries/BN254.sol";

Expand Down
6 changes: 4 additions & 2 deletions src/interfaces/IFinalityRelayerManager.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
pragma solidity ^0.8.20;

import "../libraries/BN254.sol";
import "./IBLSApkRegistry.sol";
Expand All @@ -21,6 +21,7 @@ interface IFinalityRelayerManager {
bytes32 l1BlockHash;
uint256 l1BlockNumber;
bytes32 msgHash;
uint32 disputeGameType;
}

struct PubkeyRegistrationParams {
Expand All @@ -35,7 +36,8 @@ interface IFinalityRelayerManager {

function VerifyFinalitySignature(
FinalityBatch calldata finalityBatch,
IBLSApkRegistry.FinalityNonSingerAndSignature memory finalityNonSingerAndSignature
IBLSApkRegistry.FinalityNonSingerAndSignature memory finalityNonSingerAndSignature,
uint256 minGas
) external;

function addOrRemoverOperatorWhitelist(address operator, bool isAdd) external;
Expand Down
2 changes: 1 addition & 1 deletion src/libraries/BN254.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
pragma solidity ^0.8.20;

library BN254 {
// modulus for the underlying field F_p of the elliptic curve
Expand Down
106 changes: 106 additions & 0 deletions src/libraries/SafeCall.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;


library SafeCall {
function send(
address _target,
uint256 _gas,
uint256 _value
) internal returns (bool) {
bool _success;
assembly {
_success := call(
_gas, // gas
_target, // recipient
_value, // ether value
0, // inloc
0, // inlen
0, // outloc
0 // outlen
)
}
return _success;
}

function call(
address _target,
uint256 _gas,
uint256 _value,
bytes memory _calldata
) internal returns (bool) {
bool _success;
assembly {
_success := call(
_gas, // gas
_target, // recipient
_value, // ether value
add(_calldata, 32), // inloc
mload(_calldata), // inlen
0, // outloc
0 // outlen
)
}
return _success;
}

function hasMinGas(uint256 _minGas, uint256 _reservedGas) internal view returns (bool) {
bool _hasMinGas;
assembly {
// Equation: gas × 63 ≥ minGas × 64 + 63(40_000 + reservedGas)
_hasMinGas := iszero(
lt(mul(gas(), 63), add(mul(_minGas, 64), mul(add(40000, _reservedGas), 63)))
)
}
return _hasMinGas;
}

function callWithMinGas(
address _target,
uint256 _minGas,
uint256 _value,
bytes memory _calldata
) internal returns (bool) {
bool _success;
bool _hasMinGas = hasMinGas(_minGas, 0);
assembly {
// Assertion: gasleft() >= (_minGas * 64) / 63 + 40_000
if iszero(_hasMinGas) {
// Store the "Error(string)" selector in scratch space.
mstore(0, 0x08c379a0)
// Store the pointer to the string length in scratch space.
mstore(32, 32)
// Store the string.
//
// SAFETY:
// - We pad the beginning of the string with two zero bytes as well as the
// length (24) to ensure that we override the free memory pointer at offset
// 0x40. This is necessary because the free memory pointer is likely to
// be greater than 1 byte when this function is called, but it is incredibly
// unlikely that it will be greater than 3 bytes. As for the data within
// 0x60, it is ensured that it is 0 due to 0x60 being the zero offset.
// - It's fine to clobber the free memory pointer, we're reverting.
mstore(88, 0x0000185361666543616c6c3a204e6f7420656e6f75676820676173)

// Revert with 'Error("SafeCall: Not enough gas")'
revert(28, 100)
}

// The call will be supplied at least ((_minGas * 64) / 63) gas due to the
// above assertion. This ensures that, in all circumstances (except for when the
// `_minGas` does not account for the `memory_expansion_cost` and `code_execution_cost`
// factors of the dynamic cost of the `CALL` opcode), the call will receive at least
// the minimum amount of gas specified.
_success := call(
gas(), // gas
_target, // recipient
_value, // ether value
add(_calldata, 32), // inloc
mload(_calldata), // inlen
0x00, // outloc
0x00 // outlen
)
}
return _success;
}
}

0 comments on commit c0cc7d1

Please sign in to comment.