Skip to content

Commit

Permalink
bold-c4e068b568ff662f49ed191c5c3188ea7b6138b2
Browse files Browse the repository at this point in the history
  • Loading branch information
godzillaba committed Apr 10, 2024
1 parent 90037b9 commit c3868f1
Show file tree
Hide file tree
Showing 40 changed files with 4,114 additions and 2,439 deletions.
103 changes: 103 additions & 0 deletions src/assertionStakingPool/AssertionStakingPool.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE
// SPDX-License-Identifier: BUSL-1.1
//

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../rollup/IRollupLogic.sol";
import "../rollup/IRollupCore.sol";
import "./StakingPoolErrors.sol";

/// @notice Staking pool contract for target assertion.
/// Allows users to deposit stake, create assertion once required stake amount is reached,
/// and reclaim their stake when and if the assertion is confirmed.
contract AssertionStakingPool {
using SafeERC20 for IERC20;
address public immutable rollup;
bytes32 public immutable assertionHash;
AssertionInputs public assertionInputs;
IERC20 public immutable stakeToken;
mapping(address => uint256) public depositedTokenBalances;

event StakeDeposited(address indexed sender, uint256 amount);
event StakeWithdrawn(address indexed sender, uint256 amount);

/// @param _rollup Rollup contract of target chain
/// @param _assertionInputs Inputs to be passed into Rollup.stakeOnNewAssertion
/// @param _assertionHash Assertion hash to be passed into Rollup.stakeOnNewAssertion
constructor(
address _rollup,
AssertionInputs memory _assertionInputs,
bytes32 _assertionHash
) {
rollup = _rollup;
assertionHash = _assertionHash;
assertionInputs = _assertionInputs;
stakeToken = IERC20(IRollupCore(rollup).stakeToken());
}

/// @notice Deposit stake into pool contract.
/// @param _amount amount of stake token to deposit
function depositIntoPool(uint256 _amount) external {
depositedTokenBalances[msg.sender] += _amount;
stakeToken.safeTransferFrom(msg.sender, address(this), _amount);
emit StakeDeposited(msg.sender, _amount);
}

/// @notice Create assertion. Callable only if required stake has been reached and assertion has not been asserted yet.
function createAssertion() external {
uint256 requiredStake = getRequiredStake();
// approve spending from rollup for newStakeOnNewAssertion call
stakeToken.safeIncreaseAllowance(rollup, requiredStake);
// reverts if pool doesn't have enough stake and if assertion has already been asserted
IRollupUser(rollup).newStakeOnNewAssertion(requiredStake, assertionInputs, assertionHash);
}

/// @notice Make stake withdrawable.
/// @dev Separate call from withdrawStakeBackIntoPool since returnOldDeposit reverts with 0 balance (in e.g., case of admin forceRefundStaker)
function makeStakeWithdrawable() public {
// this checks for active staker
IRollupUser(rollup).returnOldDeposit();
}

/// @notice Move stake back from rollup contract to this contract.
/// Callable only if this contract has already created an assertion and it's now inactive.
/// @dev Separate call from makeStakeWithdrawable since returnOldDeposit reverts with 0 balance (in e.g., case of admin forceRefundStaker)
function withdrawStakeBackIntoPool() public {
IRollupUser(rollup).withdrawStakerFunds();
}

/// @notice Combines makeStakeWithdrawable and withdrawStakeBackIntoPool into single call
function makeStakeWithdrawableAndWithdrawBackIntoPool() external {
makeStakeWithdrawable();
withdrawStakeBackIntoPool();
}

/// @notice Send supplied amount of stake from this contract back to its depositor.
/// @param _amount stake amount to withdraw
function withdrawFromPool(uint256 _amount) public {
uint256 balance = depositedTokenBalances[msg.sender];
if (balance == 0) {
revert NoBalanceToWithdraw(msg.sender);
}
if (_amount > balance) {
revert AmountExceedsBalance(msg.sender, _amount, balance);
}
depositedTokenBalances[msg.sender] = balance - _amount;
stakeToken.safeTransfer(msg.sender, _amount);
emit StakeWithdrawn(msg.sender, _amount);
}

/// @notice Send full balance of stake from this contract back to its depositor.
function withdrawFromPool() external {
withdrawFromPool(depositedTokenBalances[msg.sender]);
}

/// @notice Get required stake for pool's assertion.
/// Requried stake for a given assertion is set in the previous assertion's config data
function getRequiredStake() public view returns (uint256) {
return assertionInputs.beforeStateData.configData.requiredStake;
}
}
83 changes: 83 additions & 0 deletions src/assertionStakingPool/AssertionStakingPoolCreator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE
// SPDX-License-Identifier: BUSL-1.1
//

pragma solidity ^0.8.0;

import "./AssertionStakingPool.sol";
import "@openzeppelin/contracts/utils/Create2.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "./StakingPoolErrors.sol";

/// @notice Creates staking pool contract for a target assertion. Can be used for any child Arbitrum chain running on top of the deployed AssertionStakingPoolCreator's chain.
contract AssertionStakingPoolCreator {
event NewAssertionPoolCreated(
address indexed rollup,
bytes32 indexed _assertionHash,
address assertionPool
);

/// @notice Create a staking pool contract
/// @param _rollup Rollup contract of target chain
/// @param _assertionInputs Inputs to be passed into Rollup.stakeOnNewAssertion
/// @param _assertionHash Assertion hash to be passed into Rollup.stakeOnNewAssertion
function createPoolForAssertion(
address _rollup,
AssertionInputs memory _assertionInputs,
bytes32 _assertionHash
) external returns (address) {
address assertionPoolAddress = address(
new AssertionStakingPool{salt: _getPoolSalt(_rollup, _assertionInputs, _assertionHash)}(
_rollup,
_assertionInputs,
_assertionHash
)
);

emit NewAssertionPoolCreated(_rollup, _assertionHash, assertionPoolAddress);
return assertionPoolAddress;
}

/// @notice get staking pool deployed with provided inputs; reverts if pool contract doesn't exist.
/// @param _rollup Rollup contract of target chain
/// @param _assertionInputs Inputs to be passed into Rollup.stakeOnNewAssertion
/// @param _assertionHash Assertion hash to be passed into Rollup.stakeOnNewAssertion
function getPool(
address _rollup,
AssertionInputs memory _assertionInputs,
bytes32 _assertionHash
) public view returns (AssertionStakingPool) {
bytes32 salt = _getPoolSalt(_rollup, _assertionInputs, _assertionHash);
bytes32 bytecodeHash = _getPoolByteCodeHash(_rollup, _assertionInputs, _assertionHash);

address pool = Create2.computeAddress(salt, bytecodeHash, address(this));
if (Address.isContract(pool)) {
return AssertionStakingPool(pool);
} else {
revert PoolDoesntExist(_rollup, _assertionInputs, _assertionHash);
}
}

/// @notice get salt for create2 staking pool deployment
function _getPoolSalt(
address _rollup,
AssertionInputs memory _assertionInputs,
bytes32 _assertionHash
) internal pure returns (bytes32) {
return keccak256(abi.encode(_rollup, _assertionInputs, _assertionHash));
}

/// @notice get bytecodehash for create2 staking pool deployment
function _getPoolByteCodeHash(
address _rollup,
AssertionInputs memory _assertionInputs,
bytes32 _assertionHash
) internal pure returns (bytes32) {
bytes memory bytecode = type(AssertionStakingPool).creationCode;
return
keccak256(
abi.encodePacked(bytecode, abi.encode(_rollup, _assertionInputs, _assertionHash))
);
}
}
12 changes: 12 additions & 0 deletions src/assertionStakingPool/StakingPoolErrors.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE
// SPDX-License-Identifier: BUSL-1.1
//
pragma solidity ^0.8.0;
import "../rollup/IRollupLogic.sol";

error NoBalanceToWithdraw(address sender);

error PoolDoesntExist(address rollup, AssertionInputs assertionInputs, bytes32 assertionHash);

error AmountExceedsBalance(address sender, uint256 amount, uint256 balance);
133 changes: 0 additions & 133 deletions src/challenge/ChallengeLib.sol

This file was deleted.

Loading

0 comments on commit c3868f1

Please sign in to comment.