Skip to content

Commit

Permalink
fix(protocol): fix debitBond bug and add additional tests (#18443)
Browse files Browse the repository at this point in the history
  • Loading branch information
dantaik authored Nov 5, 2024
1 parent df16035 commit 75ff1f8
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 22 deletions.
15 changes: 9 additions & 6 deletions packages/protocol/contracts/layer1/based/LibBonds.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ library LibBonds {
event BondDebited(address indexed user, uint256 blockId, uint256 amount);

error L1_INVALID_MSG_VALUE();
error L1_ETH_NOT_PAID_AS_BOND();

/// @dev Deposits TAIKO tokens to be used as bonds.
/// @param _state Pointer to the protocol's storage.
Expand All @@ -48,7 +49,7 @@ library LibBonds {
public
{
_state.bondBalance[msg.sender] += _amount;
_handleDeposit(_resolver, _amount);
_handleDeposit(_resolver, msg.sender, _amount);
}

/// @dev Withdraws TAIKO tokens.
Expand Down Expand Up @@ -111,7 +112,8 @@ library LibBonds {
_state.bondBalance[_user] = balance - _amount;
}
} else {
_handleDeposit(_resolver, _amount);
// Note that the following function call will revert if bond asset is Ether.
_handleDeposit(_resolver, _user, _amount);
}
emit BondDebited(_user, _blockId, _amount);
}
Expand All @@ -138,17 +140,18 @@ library LibBonds {

/// @dev Handles the deposit of bond tokens or Ether.
/// @param _resolver The address resolver.
/// @param _user The user who made the deposit
/// @param _amount The amount of tokens or Ether to deposit.
function _handleDeposit(IAddressResolver _resolver, uint256 _amount) private {
function _handleDeposit(IAddressResolver _resolver, address _user, uint256 _amount) private {
address bondToken = _bondToken(_resolver);

if (bondToken != address(0)) {
require(msg.value == 0, L1_INVALID_MSG_VALUE());
IERC20(bondToken).transferFrom(msg.sender, address(this), _amount);
IERC20(bondToken).transferFrom(_user, address(this), _amount);
} else {
require(msg.value == _amount, L1_INVALID_MSG_VALUE());
require(msg.value == _amount, L1_ETH_NOT_PAID_AS_BOND());
}
emit BondDeposited(msg.sender, _amount);
emit BondDeposited(_user, _amount);
}

/// @dev Resolves the bond token address using the address resolver, returns address(0) if Ether
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ contract TokenUnlock is EssentialContract {
)
external
nonZeroAddr(_recipient)
nonZeroValue(uint256(_tgeTimestamp))
nonZeroValue(_tgeTimestamp)
initializer
{
if (_owner == _recipient) revert INVALID_PARAM();
Expand Down
69 changes: 69 additions & 0 deletions packages/protocol/test/layer1/based/TaikoL1TestGroup11.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "./TaikoL1TestGroupBase.sol";

contract TaikoL10TestGroup11 is TaikoL1TestGroupBase {
// Test summary:
// 1. Zachary proposes a block with a custom proposer in the block parameters
// 2. The proposal will revert as Zachary is not registered as the preconf task manager.
function test_taikoL1_group_11_case_1() external {
vm.warp(1_000_000);
printBlockAndTrans(0);

giveEthAndTko(Zachary, 10_000 ether, 1000 ether);

ITierProvider(tr).getTier(LibTiers.TIER_OPTIMISTIC);

console2.log("====== Zachary proposes a block");

TaikoData.BlockParamsV2 memory params;
params.proposer = Alice;
proposeBlock(Zachary, params, LibProposing.L1_INVALID_CUSTOM_PROPOSER.selector);
}

// Test summary:
// 1. Zachary proposes a block with a Alice as the proposer
// 2. Alice proves the block
// 3. Alice verifies the block to get back her bonds.
function test_taikoL1_group_11_case_2() external {
registerAddress("preconf_task_manager", Zachary);

vm.warp(1_000_000);
printBlockAndTrans(0);

giveEthAndTko(Zachary, 10_000 ether, 1000 ether);
giveEthAndTko(Alice, 10_000 ether, 1000 ether);

ITierProvider.Tier memory tierOp = ITierProvider(tr).getTier(LibTiers.TIER_OPTIMISTIC);

console2.log("====== Zachary proposes a block with Alice as the proposer");

TaikoData.BlockParamsV2 memory params;
params.proposer = Alice;
TaikoData.BlockMetadataV2 memory meta = proposeBlock(Zachary, params, "");

assertEq(totalTkoBalance(tko, L1, Zachary), 10_000 ether);
assertEq(totalTkoBalance(tko, L1, Alice), 10_000 ether - L1.getConfig().livenessBond);

console2.log("====== Alice proves the block");
// Prove the block
bytes32 blockHash = bytes32(uint256(10_000));
bytes32 stateRoot = bytes32(uint256(20_000));

mineAndWrap(10 seconds);
proveBlock(Alice, meta, GENESIS_BLOCK_HASH, blockHash, stateRoot, meta.minTier, "");

assertEq(totalTkoBalance(tko, L1, Zachary), 10_000 ether);
assertEq(totalTkoBalance(tko, L1, Alice), 10_000 ether - tierOp.validityBond);

printBlockAndTrans(meta.id);

console2.log("====== Alice's block is verified");
mineAndWrap(7 days);
verifyBlock(1);

assertEq(totalTkoBalance(tko, L1, Zachary), 10_000 ether);
assertEq(totalTkoBalance(tko, L1, Alice), 10_000 ether);
}
}
15 changes: 0 additions & 15 deletions packages/protocol/test/layer1/based/TaikoL1TestGroupBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,6 @@ abstract contract TaikoL1TestGroupBase is TaikoL1TestBase {
return L1.proposeBlockV2(abi.encode(params), new bytes(10));
}

function proposeBlockV2(
address proposer,
TaikoData.BlockParamsV2 memory params,
bytes4 revertReason
)
internal
returns (TaikoData.BlockMetadataV2 memory)
{
bytes memory txList = new bytes(10);

vm.prank(proposer);
if (revertReason != "") vm.expectRevert(revertReason);
return L1.proposeBlockV2(abi.encode(params), txList);
}

function proveBlock(
address prover,
TaikoData.BlockMetadataV2 memory meta,
Expand Down

0 comments on commit 75ff1f8

Please sign in to comment.